From e10baf2d7e8d21820d5bcca31e55c9607d832ca3 Mon Sep 17 00:00:00 2001 From: Mihail Stoykov Date: Mon, 10 Feb 2025 12:30:58 +0200 Subject: [PATCH] browser: race fixes in page and frame mappings Specifically for: - dbclick - dispatchEvent - fill - focus - getAttribute - hover - innerHTML - innerText - inputValue --- .../k6/browser/browser/frame_mapping.go | 85 +++++++++---- .../k6/browser/browser/page_mapping.go | 114 +++++++++++------- .../js/modules/k6/browser/common/frame.go | 48 ++------ internal/js/modules/k6/browser/common/page.go | 47 ++++---- .../modules/k6/browser/common/page_options.go | 10 +- .../modules/k6/browser/tests/browser_test.go | 8 +- .../js/modules/k6/browser/tests/frame_test.go | 8 +- .../modules/k6/browser/tests/keyboard_test.go | 16 +-- .../tests/launch_options_slowmo_test.go | 22 ++-- .../modules/k6/browser/tests/locator_test.go | 12 +- .../js/modules/k6/browser/tests/page_test.go | 51 ++++---- .../modules/k6/browser/tests/webvital_test.go | 4 +- 12 files changed, 229 insertions(+), 196 deletions(-) diff --git a/internal/js/modules/k6/browser/browser/frame_mapping.go b/internal/js/modules/k6/browser/browser/frame_mapping.go index d961e6503d9..c40d684ae47 100644 --- a/internal/js/modules/k6/browser/browser/frame_mapping.go +++ b/internal/js/modules/k6/browser/browser/frame_mapping.go @@ -45,18 +45,23 @@ func mapFrame(vu moduleVU, f *common.Frame) mapping { return f.Content() //nolint:wrapcheck }) }, - "dblclick": func(selector string, opts sobek.Value) *sobek.Promise { + "dblclick": func(selector string, opts sobek.Value) (*sobek.Promise, error) { + popts := common.NewFrameDblClickOptions(f.Timeout()) + if err := popts.Parse(vu.Context(), opts); err != nil { + return nil, fmt.Errorf("parsing double click options: %w", err) + } return k6ext.Promise(vu.Context(), func() (any, error) { - return nil, f.Dblclick(selector, opts) //nolint:wrapcheck - }) + return nil, f.Dblclick(selector, popts) //nolint:wrapcheck + }), nil }, "dispatchEvent": func(selector, typ string, eventInit, opts sobek.Value) (*sobek.Promise, error) { popts := common.NewFrameDispatchEventOptions(f.Timeout()) if err := popts.Parse(vu.Context(), opts); err != nil { return nil, fmt.Errorf("parsing frame dispatch event options: %w", err) } + earg := exportArg(eventInit) return k6ext.Promise(vu.Context(), func() (any, error) { - return nil, f.DispatchEvent(selector, typ, exportArg(eventInit), popts) //nolint:wrapcheck + return nil, f.DispatchEvent(selector, typ, earg, popts) //nolint:wrapcheck }), nil }, "evaluate": func(pageFunc sobek.Value, gargs ...sobek.Value) (*sobek.Promise, error) { @@ -79,15 +84,23 @@ func mapFrame(vu moduleVU, f *common.Frame) mapping { return mapJSHandle(vu, jsh), nil }), nil }, - "fill": func(selector, value string, opts sobek.Value) *sobek.Promise { + "fill": func(selector, value string, opts sobek.Value) (*sobek.Promise, error) { + popts := common.NewFrameFillOptions(f.Timeout()) + if err := popts.Parse(vu.Context(), opts); err != nil { + return nil, fmt.Errorf("parsing fill options: %w", err) + } return k6ext.Promise(vu.Context(), func() (any, error) { - return nil, f.Fill(selector, value, opts) //nolint:wrapcheck - }) + return nil, f.Fill(selector, value, popts) //nolint:wrapcheck + }), nil }, - "focus": func(selector string, opts sobek.Value) *sobek.Promise { + "focus": func(selector string, opts sobek.Value) (*sobek.Promise, error) { + popts := common.NewFrameBaseOptions(f.Timeout()) + if err := popts.Parse(vu.Context(), opts); err != nil { + return nil, fmt.Errorf("parsing focus options: %w", err) + } return k6ext.Promise(vu.Context(), func() (any, error) { - return nil, f.Focus(selector, opts) //nolint:wrapcheck - }) + return nil, f.Focus(selector, popts) //nolint:wrapcheck + }), nil }, "frameElement": func() *sobek.Promise { return k6ext.Promise(vu.Context(), func() (any, error) { @@ -98,17 +111,21 @@ func mapFrame(vu moduleVU, f *common.Frame) mapping { return mapElementHandle(vu, fe), nil }) }, - "getAttribute": func(selector, name string, opts sobek.Value) *sobek.Promise { + "getAttribute": func(selector, name string, opts sobek.Value) (*sobek.Promise, error) { + popts := common.NewFrameBaseOptions(f.Timeout()) + if err := popts.Parse(vu.Context(), opts); err != nil { + return nil, fmt.Errorf("parsing getAttribute options: %w", err) + } return k6ext.Promise(vu.Context(), func() (any, error) { - s, ok, err := f.GetAttribute(selector, name, opts) + s, ok, err := f.GetAttribute(selector, name, popts) if err != nil { return nil, err //nolint:wrapcheck } if !ok { - return nil, nil + return nil, nil //nolint:nilnil } return s, nil - }) + }), nil }, "goto": func(url string, opts sobek.Value) (*sobek.Promise, error) { gopts := common.NewFrameGotoOptions( @@ -127,25 +144,41 @@ func mapFrame(vu moduleVU, f *common.Frame) mapping { return mapResponse(vu, resp), nil }), nil }, - "hover": func(selector string, opts sobek.Value) *sobek.Promise { + "hover": func(selector string, opts sobek.Value) (*sobek.Promise, error) { + popts := common.NewFrameHoverOptions(f.Timeout()) + if err := popts.Parse(vu.Context(), opts); err != nil { + return nil, fmt.Errorf("parsing hover options: %w", err) + } return k6ext.Promise(vu.Context(), func() (any, error) { - return nil, f.Hover(selector, opts) //nolint:wrapcheck - }) + return nil, f.Hover(selector, popts) //nolint:wrapcheck + }), nil }, - "innerHTML": func(selector string, opts sobek.Value) *sobek.Promise { + "innerHTML": func(selector string, opts sobek.Value) (*sobek.Promise, error) { + popts := common.NewFrameInnerHTMLOptions(f.Timeout()) + if err := popts.Parse(vu.Context(), opts); err != nil { + return nil, fmt.Errorf("parsing inner HTML options: %w", err) + } return k6ext.Promise(vu.Context(), func() (any, error) { - return f.InnerHTML(selector, opts) //nolint:wrapcheck - }) + return f.InnerHTML(selector, popts) //nolint:wrapcheck + }), nil }, - "innerText": func(selector string, opts sobek.Value) *sobek.Promise { + "innerText": func(selector string, opts sobek.Value) (*sobek.Promise, error) { + popts := common.NewFrameInnerTextOptions(f.Timeout()) + if err := popts.Parse(vu.Context(), opts); err != nil { + return nil, fmt.Errorf("parsing inner text options: %w", err) + } return k6ext.Promise(vu.Context(), func() (any, error) { - return f.InnerText(selector, opts) //nolint:wrapcheck - }) + return f.InnerText(selector, popts) //nolint:wrapcheck + }), nil }, - "inputValue": func(selector string, opts sobek.Value) *sobek.Promise { + "inputValue": func(selector string, opts sobek.Value) (*sobek.Promise, error) { + popts := common.NewFrameInputValueOptions(f.Timeout()) + if err := popts.Parse(vu.Context(), opts); err != nil { + return nil, fmt.Errorf("parsing input value options: %w", err) + } return k6ext.Promise(vu.Context(), func() (any, error) { - return f.InputValue(selector, opts) //nolint:wrapcheck - }) + return f.InputValue(selector, popts) //nolint:wrapcheck + }), nil }, "isChecked": func(selector string, opts sobek.Value) *sobek.Promise { return k6ext.Promise(vu.Context(), func() (any, error) { diff --git a/internal/js/modules/k6/browser/browser/page_mapping.go b/internal/js/modules/k6/browser/browser/page_mapping.go index d55368be162..f634e6d9787 100644 --- a/internal/js/modules/k6/browser/browser/page_mapping.go +++ b/internal/js/modules/k6/browser/browser/page_mapping.go @@ -29,7 +29,7 @@ func mapPage(vu moduleVU, p *common.Page) mapping { //nolint:gocognit,cyclop }) }, "click": func(selector string, opts sobek.Value) (*sobek.Promise, error) { - popts, err := parseFrameClickOptions(vu.Context(), opts, p.Timeout()) + popts, err := parseFrameClickOptions(vu.Context(), opts, p.MainFrame().Timeout()) if err != nil { return nil, err } @@ -40,13 +40,14 @@ func mapPage(vu moduleVU, p *common.Page) mapping { //nolint:gocognit,cyclop }), nil }, "close": func(opts sobek.Value) *sobek.Promise { + // TODO when opts are implemented for this function pares them here before calling k6ext.Promise and doing it + // in a goroutine off the event loop. As that will race with anything running on the event loop. return k6ext.Promise(vu.Context(), func() (any, error) { // It's safe to close the taskqueue for this targetID (if one // exists). vu.taskQueueRegistry.close(p.TargetID()) - // TODO(@mstoykov): don't use sobek Values in a separate goroutine - return nil, p.Close(opts) //nolint:wrapcheck + return nil, p.Close() //nolint:wrapcheck }) }, "content": func() *sobek.Promise { @@ -57,26 +58,33 @@ func mapPage(vu moduleVU, p *common.Page) mapping { //nolint:gocognit,cyclop "context": func() mapping { return mapBrowserContext(vu, p.Context()) }, - "dblclick": func(selector string, opts sobek.Value) *sobek.Promise { + "dblclick": func(selector string, opts sobek.Value) (*sobek.Promise, error) { + popts := common.NewFrameDblClickOptions(p.MainFrame().Timeout()) + if err := popts.Parse(vu.Context(), opts); err != nil { + return nil, fmt.Errorf("parsing double click options: %w", err) + } return k6ext.Promise(vu.Context(), func() (any, error) { - // TODO(@mstoykov): don't use sobek Values in a separate goroutine - return nil, p.Dblclick(selector, opts) //nolint:wrapcheck - }) + return nil, p.Dblclick(selector, popts) //nolint:wrapcheck + }), nil }, "dispatchEvent": func(selector, typ string, eventInit, opts sobek.Value) (*sobek.Promise, error) { - popts := common.NewFrameDispatchEventOptions(p.Timeout()) + popts := common.NewFrameDispatchEventOptions(p.MainFrame().Timeout()) if err := popts.Parse(vu.Context(), opts); err != nil { return nil, fmt.Errorf("parsing page dispatch event options: %w", err) } + earg := exportArg(eventInit) return k6ext.Promise(vu.Context(), func() (any, error) { - return nil, p.DispatchEvent(selector, typ, exportArg(eventInit), popts) //nolint:wrapcheck + return nil, p.DispatchEvent(selector, typ, earg, popts) //nolint:wrapcheck }), nil }, - "emulateMedia": func(opts sobek.Value) *sobek.Promise { + "emulateMedia": func(opts sobek.Value) (*sobek.Promise, error) { + popts := common.NewPageEmulateMediaOptions(p) + if err := popts.Parse(vu.Context(), opts); err != nil { + return nil, fmt.Errorf("parsing emulateMedia options: %w", err) + } return k6ext.Promise(vu.Context(), func() (any, error) { - // TODO(@mstoykov): don't use sobek Values in a separate goroutine - return nil, p.EmulateMedia(opts) //nolint:wrapcheck - }) + return nil, p.EmulateMedia(popts) //nolint:wrapcheck + }), nil }, "emulateVisionDeficiency": func(typ string) *sobek.Promise { return k6ext.Promise(vu.Context(), func() (any, error) { @@ -108,17 +116,23 @@ func mapPage(vu moduleVU, p *common.Page) mapping { //nolint:gocognit,cyclop return mapJSHandle(vu, jsh), nil }), nil }, - "fill": func(selector string, value string, opts sobek.Value) *sobek.Promise { + "fill": func(selector string, value string, opts sobek.Value) (*sobek.Promise, error) { + popts := common.NewFrameFillOptions(p.MainFrame().Timeout()) + if err := popts.Parse(vu.Context(), opts); err != nil { + return nil, fmt.Errorf("parsing fill options: %w", err) + } return k6ext.Promise(vu.Context(), func() (any, error) { - // TODO(@mstoykov): don't use sobek Values in a separate goroutine - return nil, p.Fill(selector, value, opts) //nolint:wrapcheck - }) + return nil, p.Fill(selector, value, popts) //nolint:wrapcheck + }), nil }, - "focus": func(selector string, opts sobek.Value) *sobek.Promise { + "focus": func(selector string, opts sobek.Value) (*sobek.Promise, error) { + popts := common.NewFrameBaseOptions(p.MainFrame().Timeout()) + if err := popts.Parse(vu.Context(), opts); err != nil { + return nil, fmt.Errorf("parsing focus options: %w", err) + } return k6ext.Promise(vu.Context(), func() (any, error) { - // TODO(@mstoykov): don't use sobek Values in a separate goroutine - return nil, p.Focus(selector, opts) //nolint:wrapcheck - }) + return nil, p.Focus(selector, popts) //nolint:wrapcheck + }), nil }, "frames": func() *sobek.Object { var ( @@ -130,18 +144,21 @@ func mapPage(vu moduleVU, p *common.Page) mapping { //nolint:gocognit,cyclop } return rt.ToValue(mfrs).ToObject(rt) }, - "getAttribute": func(selector string, name string, opts sobek.Value) *sobek.Promise { + "getAttribute": func(selector string, name string, opts sobek.Value) (*sobek.Promise, error) { + popts := common.NewFrameBaseOptions(p.MainFrame().Timeout()) + if err := popts.Parse(vu.Context(), opts); err != nil { + return nil, fmt.Errorf("parsing getAttribute options: %w", err) + } return k6ext.Promise(vu.Context(), func() (any, error) { - // TODO(@mstoykov): don't use sobek Values in a separate goroutine - s, ok, err := p.GetAttribute(selector, name, opts) + s, ok, err := p.GetAttribute(selector, name, popts) if err != nil { return nil, err //nolint:wrapcheck } if !ok { - return nil, nil + return nil, nil //nolint:nilnil } return s, nil - }) + }), nil }, "goto": func(url string, opts sobek.Value) (*sobek.Promise, error) { gopts := common.NewFrameGotoOptions( @@ -157,32 +174,45 @@ func mapPage(vu moduleVU, p *common.Page) mapping { //nolint:gocognit,cyclop return nil, err //nolint:wrapcheck } + // TODO(@mstoykov): don't use sobek Values in a separate goroutine - this uses the runtime in a lot of the cases return mapResponse(vu, resp), nil }), nil }, - "hover": func(selector string, opts sobek.Value) *sobek.Promise { + "hover": func(selector string, opts sobek.Value) (*sobek.Promise, error) { + popts := common.NewFrameHoverOptions(p.MainFrame().Timeout()) + if err := popts.Parse(vu.Context(), opts); err != nil { + return nil, fmt.Errorf("parsing hover options: %w", err) + } return k6ext.Promise(vu.Context(), func() (any, error) { - // TODO(@mstoykov): don't use sobek Values in a separate goroutine - return nil, p.Hover(selector, opts) //nolint:wrapcheck - }) + return nil, p.Hover(selector, popts) //nolint:wrapcheck + }), nil }, - "innerHTML": func(selector string, opts sobek.Value) *sobek.Promise { + "innerHTML": func(selector string, opts sobek.Value) (*sobek.Promise, error) { + popts := common.NewFrameInnerHTMLOptions(p.MainFrame().Timeout()) + if err := popts.Parse(vu.Context(), opts); err != nil { + return nil, fmt.Errorf("parsing inner HTML options: %w", err) + } return k6ext.Promise(vu.Context(), func() (any, error) { - // TODO(@mstoykov): don't use sobek Values in a separate goroutine - return p.InnerHTML(selector, opts) //nolint:wrapcheck - }) + return p.InnerHTML(selector, popts) //nolint:wrapcheck + }), nil }, - "innerText": func(selector string, opts sobek.Value) *sobek.Promise { + "innerText": func(selector string, opts sobek.Value) (*sobek.Promise, error) { + popts := common.NewFrameInnerTextOptions(p.MainFrame().Timeout()) + if err := popts.Parse(vu.Context(), opts); err != nil { + return nil, fmt.Errorf("parsing inner text options: %w", err) + } return k6ext.Promise(vu.Context(), func() (any, error) { - // TODO(@mstoykov): don't use sobek Values in a separate goroutine - return p.InnerText(selector, opts) //nolint:wrapcheck - }) + return p.InnerText(selector, popts) //nolint:wrapcheck + }), nil }, - "inputValue": func(selector string, opts sobek.Value) *sobek.Promise { + "inputValue": func(selector string, opts sobek.Value) (*sobek.Promise, error) { + popts := common.NewFrameInputValueOptions(p.MainFrame().Timeout()) + if err := popts.Parse(vu.Context(), opts); err != nil { + return nil, fmt.Errorf("parsing input value options: %w", err) + } return k6ext.Promise(vu.Context(), func() (any, error) { - // TODO(@mstoykov): don't use sobek Values in a separate goroutine - return p.InputValue(selector, opts) //nolint:wrapcheck - }) + return p.InputValue(selector, popts) //nolint:wrapcheck + }), nil }, "isChecked": func(selector string, opts sobek.Value) *sobek.Promise { return k6ext.Promise(vu.Context(), func() (any, error) { diff --git a/internal/js/modules/k6/browser/common/frame.go b/internal/js/modules/k6/browser/common/frame.go index 3fdf40ba58d..2d053566b9a 100644 --- a/internal/js/modules/k6/browser/common/frame.go +++ b/internal/js/modules/k6/browser/common/frame.go @@ -749,13 +749,9 @@ func (f *Frame) Content() (string, error) { } // Dblclick double clicks an element matching provided selector. -func (f *Frame) Dblclick(selector string, opts sobek.Value) error { +func (f *Frame) Dblclick(selector string, popts *FrameDblclickOptions) error { f.log.Debugf("Frame:DblClick", "fid:%s furl:%q sel:%q", f.ID(), f.URL(), selector) - popts := NewFrameDblClickOptions(f.defaultTimeout()) - if err := popts.Parse(f.ctx, opts); err != nil { - return fmt.Errorf("parsing double click options: %w", err) - } if err := f.dblclick(selector, popts); err != nil { return fmt.Errorf("double clicking on %q: %w", selector, err) } @@ -888,13 +884,9 @@ func (f *Frame) EvaluateHandle(pageFunc string, args ...any) (handle JSHandleAPI } // Fill fills out the first element found that matches the selector. -func (f *Frame) Fill(selector, value string, opts sobek.Value) error { +func (f *Frame) Fill(selector, value string, popts *FrameFillOptions) error { f.log.Debugf("Frame:Fill", "fid:%s furl:%q sel:%q val:%q", f.ID(), f.URL(), selector, value) - popts := NewFrameFillOptions(f.defaultTimeout()) - if err := popts.Parse(f.ctx, opts); err != nil { - return fmt.Errorf("parsing fill options: %w", err) - } if err := f.fill(selector, value, popts); err != nil { return fmt.Errorf("filling %q with %q: %w", selector, value, err) } @@ -921,13 +913,9 @@ func (f *Frame) fill(selector, value string, opts *FrameFillOptions) error { } // Focus focuses on the first element that matches the selector. -func (f *Frame) Focus(selector string, opts sobek.Value) error { +func (f *Frame) Focus(selector string, popts *FrameBaseOptions) error { f.log.Debugf("Frame:Focus", "fid:%s furl:%q sel:%q", f.ID(), f.URL(), selector) - popts := NewFrameBaseOptions(f.defaultTimeout()) - if err := popts.Parse(f.ctx, opts); err != nil { - return fmt.Errorf("parsing focus options: %w", err) - } if err := f.focus(selector, popts); err != nil { return fmt.Errorf("focusing %q: %w", selector, err) } @@ -965,13 +953,9 @@ func (f *Frame) FrameElement() (*ElementHandle, error) { // GetAttribute of the first element found that matches the selector. // The second return value is true if the attribute exists, and false otherwise. -func (f *Frame) GetAttribute(selector, name string, opts sobek.Value) (string, bool, error) { +func (f *Frame) GetAttribute(selector, name string, popts *FrameBaseOptions) (string, bool, error) { f.log.Debugf("Frame:GetAttribute", "fid:%s furl:%q sel:%q name:%s", f.ID(), f.URL(), selector, name) - popts := NewFrameBaseOptions(f.defaultTimeout()) - if err := popts.Parse(f.ctx, opts); err != nil { - return "", false, fmt.Errorf("parsing get attribute options: %w", err) - } s, ok, err := f.getAttribute(selector, name, popts) if err != nil { return "", false, fmt.Errorf("getting attribute %q of %q: %w", name, selector, err) @@ -1035,13 +1019,9 @@ func (f *Frame) Goto(url string, opts *FrameGotoOptions) (*Response, error) { } // Hover moves the pointer over the first element that matches the selector. -func (f *Frame) Hover(selector string, opts sobek.Value) error { +func (f *Frame) Hover(selector string, popts *FrameHoverOptions) error { f.log.Debugf("Frame:Hover", "fid:%s furl:%q sel:%q", f.ID(), f.URL(), selector) - popts := NewFrameHoverOptions(f.defaultTimeout()) - if err := popts.Parse(f.ctx, opts); err != nil { - return fmt.Errorf("parsing hover options: %w", err) - } if err := f.hover(selector, popts); err != nil { return fmt.Errorf("hovering %q: %w", selector, err) } @@ -1067,13 +1047,9 @@ func (f *Frame) hover(selector string, opts *FrameHoverOptions) error { // InnerHTML returns the innerHTML attribute of the first element found // that matches the selector. -func (f *Frame) InnerHTML(selector string, opts sobek.Value) (string, error) { +func (f *Frame) InnerHTML(selector string, popts *FrameInnerHTMLOptions) (string, error) { f.log.Debugf("Frame:InnerHTML", "fid:%s furl:%q sel:%q", f.ID(), f.URL(), selector) - popts := NewFrameInnerHTMLOptions(f.defaultTimeout()) - if err := popts.Parse(f.ctx, opts); err != nil { - return "", fmt.Errorf("parsing inner HTML options: %w", err) - } v, err := f.innerHTML(selector, popts) if err != nil { return "", fmt.Errorf("getting inner HTML of %q: %w", selector, err) @@ -1107,13 +1083,9 @@ func (f *Frame) innerHTML(selector string, opts *FrameInnerHTMLOptions) (string, // InnerText returns the inner text of the first element found // that matches the selector. -func (f *Frame) InnerText(selector string, opts sobek.Value) (string, error) { +func (f *Frame) InnerText(selector string, popts *FrameInnerTextOptions) (string, error) { f.log.Debugf("Frame:InnerText", "fid:%s furl:%q sel:%q", f.ID(), f.URL(), selector) - popts := NewFrameInnerTextOptions(f.defaultTimeout()) - if err := popts.Parse(f.ctx, opts); err != nil { - return "", fmt.Errorf("parsing inner text options: %w", err) - } v, err := f.innerText(selector, popts) if err != nil { return "", fmt.Errorf("getting inner text of %q: %w", selector, err) @@ -1146,13 +1118,9 @@ func (f *Frame) innerText(selector string, opts *FrameInnerTextOptions) (string, } // InputValue returns the input value of the first element found that matches the selector. -func (f *Frame) InputValue(selector string, opts sobek.Value) (string, error) { +func (f *Frame) InputValue(selector string, popts *FrameInputValueOptions) (string, error) { f.log.Debugf("Frame:InputValue", "fid:%s furl:%q sel:%q", f.ID(), f.URL(), selector) - popts := NewFrameInputValueOptions(f.defaultTimeout()) - if err := popts.Parse(f.ctx, opts); err != nil { - return "", fmt.Errorf("parsing input value options: %w", err) - } v, err := f.inputValue(selector, popts) if err != nil { return "", fmt.Errorf("getting input value of %q: %w", selector, err) diff --git a/internal/js/modules/k6/browser/common/page.go b/internal/js/modules/k6/browser/common/page.go index b932e18f839..8bdea5aee6d 100644 --- a/internal/js/modules/k6/browser/common/page.go +++ b/internal/js/modules/k6/browser/common/page.go @@ -849,7 +849,7 @@ func (p *Page) Click(selector string, opts *FrameClickOptions) error { } // Close closes the page. -func (p *Page) Close(_ sobek.Value) error { +func (p *Page) Close() error { p.logger.Debugf("Page:Close", "sid:%v", p.sessionID()) _, span := TraceAPICall(p.ctx, p.targetID.String(), "page.close") defer span.End() @@ -907,10 +907,10 @@ func (p *Page) Context() *BrowserContext { } // Dblclick double clicks an element matching provided selector. -func (p *Page) Dblclick(selector string, opts sobek.Value) error { +func (p *Page) Dblclick(selector string, popts *FrameDblclickOptions) error { p.logger.Debugf("Page:Dblclick", "sid:%v selector:%s", p.sessionID(), selector) - return p.MainFrame().Dblclick(selector, opts) + return p.MainFrame().Dblclick(selector, popts) } // DispatchEvent dispatches an event on the page to the element that matches the provided selector. @@ -921,17 +921,12 @@ func (p *Page) DispatchEvent(selector string, typ string, eventInit any, opts *F } // EmulateMedia emulates the given media type. -func (p *Page) EmulateMedia(opts sobek.Value) error { +func (p *Page) EmulateMedia(popts *PageEmulateMediaOptions) error { p.logger.Debugf("Page:EmulateMedia", "sid:%v", p.sessionID()) - parsedOpts := NewPageEmulateMediaOptions(p.mediaType, p.colorScheme, p.reducedMotion) - if err := parsedOpts.Parse(p.ctx, opts); err != nil { - return fmt.Errorf("parsing emulateMedia options: %w", err) - } - - p.mediaType = parsedOpts.Media - p.colorScheme = parsedOpts.ColorScheme - p.reducedMotion = parsedOpts.ReducedMotion + p.mediaType = popts.Media + p.colorScheme = popts.ColorScheme + p.reducedMotion = popts.ReducedMotion p.frameSessionsMu.RLock() for _, fs := range p.frameSessions { @@ -993,17 +988,17 @@ func (p *Page) EvaluateHandle(pageFunc string, args ...any) (JSHandleAPI, error) } // Fill fills an input element with the provided value. -func (p *Page) Fill(selector string, value string, opts sobek.Value) error { +func (p *Page) Fill(selector string, value string, popts *FrameFillOptions) error { p.logger.Debugf("Page:Fill", "sid:%v selector:%s", p.sessionID(), selector) - return p.MainFrame().Fill(selector, value, opts) + return p.MainFrame().Fill(selector, value, popts) } // Focus focuses an element matching the provided selector. -func (p *Page) Focus(selector string, opts sobek.Value) error { +func (p *Page) Focus(selector string, popts *FrameBaseOptions) error { p.logger.Debugf("Page:Focus", "sid:%v selector:%s", p.sessionID(), selector) - return p.MainFrame().Focus(selector, opts) + return p.MainFrame().Focus(selector, popts) } // Frames returns a list of frames on the page. @@ -1013,11 +1008,11 @@ func (p *Page) Frames() []*Frame { // GetAttribute returns the attribute value of the element matching the provided selector. // The second return value is true if the attribute exists, and false otherwise. -func (p *Page) GetAttribute(selector string, name string, opts sobek.Value) (string, bool, error) { +func (p *Page) GetAttribute(selector string, name string, popts *FrameBaseOptions) (string, bool, error) { p.logger.Debugf("Page:GetAttribute", "sid:%v selector:%s name:%s", p.sessionID(), selector, name) - return p.MainFrame().GetAttribute(selector, name, opts) + return p.MainFrame().GetAttribute(selector, name, popts) } // GetKeyboard returns the keyboard for the page. @@ -1056,31 +1051,31 @@ func (p *Page) Goto(url string, opts *FrameGotoOptions) (*Response, error) { } // Hover hovers over an element matching the provided selector. -func (p *Page) Hover(selector string, opts sobek.Value) error { +func (p *Page) Hover(selector string, popts *FrameHoverOptions) error { p.logger.Debugf("Page:Hover", "sid:%v selector:%s", p.sessionID(), selector) - return p.MainFrame().Hover(selector, opts) + return p.MainFrame().Hover(selector, popts) } // InnerHTML returns the inner HTML of the element matching the provided selector. -func (p *Page) InnerHTML(selector string, opts sobek.Value) (string, error) { +func (p *Page) InnerHTML(selector string, popts *FrameInnerHTMLOptions) (string, error) { p.logger.Debugf("Page:InnerHTML", "sid:%v selector:%s", p.sessionID(), selector) - return p.MainFrame().InnerHTML(selector, opts) + return p.MainFrame().InnerHTML(selector, popts) } // InnerText returns the inner text of the element matching the provided selector. -func (p *Page) InnerText(selector string, opts sobek.Value) (string, error) { +func (p *Page) InnerText(selector string, popts *FrameInnerTextOptions) (string, error) { p.logger.Debugf("Page:InnerText", "sid:%v selector:%s", p.sessionID(), selector) - return p.MainFrame().InnerText(selector, opts) + return p.MainFrame().InnerText(selector, popts) } // InputValue returns the value of the input element matching the provided selector. -func (p *Page) InputValue(selector string, opts sobek.Value) (string, error) { +func (p *Page) InputValue(selector string, popts *FrameInputValueOptions) (string, error) { p.logger.Debugf("Page:InputValue", "sid:%v selector:%s", p.sessionID(), selector) - return p.MainFrame().InputValue(selector, opts) + return p.MainFrame().InputValue(selector, popts) } func (p *Page) IsClosed() bool { diff --git a/internal/js/modules/k6/browser/common/page_options.go b/internal/js/modules/k6/browser/common/page_options.go index dcc696f5dce..0013e4789b9 100644 --- a/internal/js/modules/k6/browser/common/page_options.go +++ b/internal/js/modules/k6/browser/common/page_options.go @@ -32,13 +32,11 @@ type PageScreenshotOptions struct { Quality int64 `json:"quality"` } -func NewPageEmulateMediaOptions( - defaultMedia MediaType, defaultColorScheme ColorScheme, defaultReducedMotion ReducedMotion, -) *PageEmulateMediaOptions { +func NewPageEmulateMediaOptions(from *Page) *PageEmulateMediaOptions { return &PageEmulateMediaOptions{ - ColorScheme: defaultColorScheme, - Media: defaultMedia, - ReducedMotion: defaultReducedMotion, + ColorScheme: from.colorScheme, + Media: from.mediaType, + ReducedMotion: from.reducedMotion, } } diff --git a/internal/js/modules/k6/browser/tests/browser_test.go b/internal/js/modules/k6/browser/tests/browser_test.go index be541da04bd..ef01fe5845f 100644 --- a/internal/js/modules/k6/browser/tests/browser_test.go +++ b/internal/js/modules/k6/browser/tests/browser_test.go @@ -34,7 +34,7 @@ func TestBrowserNewPage(t *testing.T) { _, err := b.Browser.NewPage(nil) assert.EqualError(t, err, "new page: existing browser context must be closed before creating a new one") - err = p1.Close(nil) + err = p1.Close() require.NoError(t, err) c = b.Context() assert.NotNil(t, c) @@ -91,7 +91,7 @@ func TestTmpDirCleanup(t *testing.T) { withEnvLookup(env.ConstLookup("TMPDIR", tmpDirPath)), ) p := b.NewPage(nil) - err = p.Close(nil) + err = p.Close() require.NoError(t, err) matches, err := filepath.Glob(filepath.Join(tmpDirPath, storage.K6BrowserDataDirPattern)) @@ -354,13 +354,13 @@ func TestMultiConnectToSingleBrowser(t *testing.T) { bctx2, err := b2.NewContext(nil) require.NoError(t, err) - err = p1.Close(nil) + err = p1.Close() require.NoError(t, err, "failed to close page #1") require.NoError(t, bctx1.Close()) p2, err := bctx2.NewPage() require.NoError(t, err, "failed to create page #2") - err = p2.Close(nil) + err = p2.Close() require.NoError(t, err, "failed to close page #2") } diff --git a/internal/js/modules/k6/browser/tests/frame_test.go b/internal/js/modules/k6/browser/tests/frame_test.go index ad7281465f7..6a2c80df7bb 100644 --- a/internal/js/modules/k6/browser/tests/frame_test.go +++ b/internal/js/modules/k6/browser/tests/frame_test.go @@ -32,7 +32,7 @@ func TestFramePress(t *testing.T) { require.NoError(t, f.Press("#text1", "KeyB", nil)) require.NoError(t, f.Press("#text1", "Shift+KeyC", nil)) - inputValue, err := f.InputValue("#text1", nil) + inputValue, err := f.InputValue("#text1", common.NewFrameInputValueOptions(p.MainFrame().Timeout())) require.NoError(t, err) require.Equal(t, "AbC", inputValue) } @@ -184,7 +184,7 @@ func TestFrameGetAttribute(t *testing.T) { err := p.SetContent(`Something`, nil) require.NoError(t, err) - got, ok, err := p.Frames()[0].GetAttribute("#el", "href", nil) + got, ok, err := p.Frames()[0].GetAttribute("#el", "href", common.NewFrameBaseOptions(p.MainFrame().Timeout())) require.NoError(t, err) require.True(t, ok) assert.Equal(t, "null", got) @@ -197,7 +197,7 @@ func TestFrameGetAttributeMissing(t *testing.T) { err := p.SetContent(`Something`, nil) require.NoError(t, err) - got, ok, err := p.Frames()[0].GetAttribute("#el", "missing", nil) + got, ok, err := p.Frames()[0].GetAttribute("#el", "missing", common.NewFrameBaseOptions(p.MainFrame().Timeout())) require.NoError(t, err) require.False(t, ok) assert.Equal(t, "", got) @@ -210,7 +210,7 @@ func TestFrameGetAttributeEmpty(t *testing.T) { err := p.SetContent(`Something`, nil) require.NoError(t, err) - got, ok, err := p.Frames()[0].GetAttribute("#el", "empty", nil) + got, ok, err := p.Frames()[0].GetAttribute("#el", "empty", common.NewFrameBaseOptions(p.MainFrame().Timeout())) require.NoError(t, err) require.True(t, ok) assert.Equal(t, "", got) diff --git a/internal/js/modules/k6/browser/tests/keyboard_test.go b/internal/js/modules/k6/browser/tests/keyboard_test.go index 223e87d0734..aa6a6cd9d8a 100644 --- a/internal/js/modules/k6/browser/tests/keyboard_test.go +++ b/internal/js/modules/k6/browser/tests/keyboard_test.go @@ -44,7 +44,7 @@ func TestKeyboardPress(t *testing.T) { require.NoError(t, err) el, err := p.Query("input") require.NoError(t, err) - require.NoError(t, p.Focus("input", nil)) + require.NoError(t, p.Focus("input", common.NewFrameBaseOptions(p.MainFrame().Timeout()))) require.NoError(t, kb.Type("Hello World!", common.KeyboardOptions{})) v, err := el.InputValue(nil) @@ -68,7 +68,7 @@ func TestKeyboardPress(t *testing.T) { require.NoError(t, err) el, err := p.Query("input") require.NoError(t, err) - require.NoError(t, p.Focus("input", nil)) + require.NoError(t, p.Focus("input", common.NewFrameBaseOptions(p.MainFrame().Timeout()))) require.NoError(t, kb.Press("Shift++", common.KeyboardOptions{})) require.NoError(t, kb.Press("Shift+=", common.KeyboardOptions{})) @@ -167,7 +167,7 @@ func TestKeyboardPress(t *testing.T) { require.NoError(t, err) el, err := p.Query("input") require.NoError(t, err) - require.NoError(t, p.Focus("input", nil)) + require.NoError(t, p.Focus("input", common.NewFrameBaseOptions(p.MainFrame().Timeout()))) require.NoError(t, kb.Press("Shift+KeyA", common.KeyboardOptions{})) require.NoError(t, kb.Press("Shift+b", common.KeyboardOptions{})) @@ -199,7 +199,7 @@ func TestKeyboardPress(t *testing.T) { require.NoError(t, err) el, err := p.Query("textarea") require.NoError(t, err) - require.NoError(t, p.Focus("textarea", nil)) + require.NoError(t, p.Focus("textarea", common.NewFrameBaseOptions(p.MainFrame().Timeout()))) require.NoError(t, kb.Type("L+m+KeyN", common.KeyboardOptions{})) v, err := el.InputValue(nil) @@ -218,7 +218,7 @@ func TestKeyboardPress(t *testing.T) { require.NoError(t, err) el, err := p.Query("textarea") require.NoError(t, err) - require.NoError(t, p.Focus("textarea", nil)) + require.NoError(t, p.Focus("textarea", common.NewFrameBaseOptions(p.MainFrame().Timeout()))) require.NoError(t, kb.Press("C", common.KeyboardOptions{})) require.NoError(t, kb.Press("d", common.KeyboardOptions{})) @@ -249,7 +249,7 @@ func TestKeyboardPress(t *testing.T) { require.NoError(t, err) el, err := p.Query("textarea") require.NoError(t, err) - require.NoError(t, p.Focus("textarea", nil)) + require.NoError(t, p.Focus("textarea", common.NewFrameBaseOptions(p.MainFrame().Timeout()))) require.NoError(t, kb.Down("Shift")) require.NoError(t, kb.Type("oPqR", common.KeyboardOptions{})) @@ -271,7 +271,7 @@ func TestKeyboardPress(t *testing.T) { require.NoError(t, err) el, err := p.Query("textarea") require.NoError(t, err) - require.NoError(t, p.Focus("textarea", nil)) + require.NoError(t, p.Focus("textarea", common.NewFrameBaseOptions(p.MainFrame().Timeout()))) require.NoError(t, kb.Type("Hello", common.KeyboardOptions{})) require.NoError(t, kb.Press("Enter", common.KeyboardOptions{})) @@ -294,7 +294,7 @@ func TestKeyboardPress(t *testing.T) { require.NoError(t, err) el, err := p.Query("input") require.NoError(t, err) - require.NoError(t, p.Focus("input", nil)) + require.NoError(t, p.Focus("input", common.NewFrameBaseOptions(p.MainFrame().Timeout()))) require.NoError(t, kb.Type("Hello World!", common.KeyboardOptions{})) v, err := el.InputValue(nil) diff --git a/internal/js/modules/k6/browser/tests/launch_options_slowmo_test.go b/internal/js/modules/k6/browser/tests/launch_options_slowmo_test.go index d402bb854d7..92c26060095 100644 --- a/internal/js/modules/k6/browser/tests/launch_options_slowmo_test.go +++ b/internal/js/modules/k6/browser/tests/launch_options_slowmo_test.go @@ -38,7 +38,7 @@ func TestBrowserOptionsSlowMo(t *testing.T) { t.Parallel() tb := newTestBrowser(t, withFileServer()) testPageSlowMoImpl(t, tb, func(_ *testBrowser, p *common.Page) { - err := p.Dblclick("button", nil) + err := p.Dblclick("button", common.NewFrameDblClickOptions(p.Timeout())) require.NoError(t, err) }) }) @@ -54,11 +54,13 @@ func TestBrowserOptionsSlowMo(t *testing.T) { t.Parallel() tb := newTestBrowser(t, withFileServer()) testPageSlowMoImpl(t, tb, func(_ *testBrowser, p *common.Page) { - err := p.EmulateMedia(tb.toSobekValue(struct { + popts := common.NewPageEmulateMediaOptions(p) + require.NoError(t, popts.Parse(tb.context(), tb.toSobekValue(struct { Media string `js:"media"` }{ Media: "print", - })) + }))) + err := p.EmulateMedia(popts) require.NoError(t, err) }) }) @@ -82,7 +84,7 @@ func TestBrowserOptionsSlowMo(t *testing.T) { t.Parallel() tb := newTestBrowser(t, withFileServer()) testPageSlowMoImpl(t, tb, func(_ *testBrowser, p *common.Page) { - err := p.Fill(".fill", "foo", nil) + err := p.Fill(".fill", "foo", common.NewFrameFillOptions(p.MainFrame().Timeout())) require.NoError(t, err) }) }) @@ -90,7 +92,7 @@ func TestBrowserOptionsSlowMo(t *testing.T) { t.Parallel() tb := newTestBrowser(t, withFileServer()) testPageSlowMoImpl(t, tb, func(_ *testBrowser, p *common.Page) { - err := p.Focus("button", nil) + err := p.Focus("button", common.NewFrameBaseOptions(p.MainFrame().Timeout())) require.NoError(t, err) }) }) @@ -112,7 +114,7 @@ func TestBrowserOptionsSlowMo(t *testing.T) { t.Parallel() tb := newTestBrowser(t, withFileServer()) testPageSlowMoImpl(t, tb, func(_ *testBrowser, p *common.Page) { - err := p.Hover("button", nil) + err := p.Hover("button", common.NewFrameHoverOptions(p.MainFrame().Timeout())) require.NoError(t, err) }) }) @@ -191,7 +193,7 @@ func TestBrowserOptionsSlowMo(t *testing.T) { t.Parallel() tb := newTestBrowser(t, withFileServer()) testFrameSlowMoImpl(t, tb, func(_ *testBrowser, f *common.Frame) { - err := f.Dblclick("button", nil) + err := f.Dblclick("button", common.NewFrameDblClickOptions(f.Timeout())) require.NoError(t, err) }) }) @@ -223,7 +225,7 @@ func TestBrowserOptionsSlowMo(t *testing.T) { t.Parallel() tb := newTestBrowser(t, withFileServer()) testFrameSlowMoImpl(t, tb, func(_ *testBrowser, f *common.Frame) { - err := f.Fill(".fill", "foo", nil) + err := f.Fill(".fill", "foo", common.NewFrameFillOptions(f.Timeout())) require.NoError(t, err) }) }) @@ -231,7 +233,7 @@ func TestBrowserOptionsSlowMo(t *testing.T) { t.Parallel() tb := newTestBrowser(t, withFileServer()) testFrameSlowMoImpl(t, tb, func(_ *testBrowser, f *common.Frame) { - err := f.Focus("button", nil) + err := f.Focus("button", common.NewFrameBaseOptions(f.Timeout())) require.NoError(t, err) }) }) @@ -252,7 +254,7 @@ func TestBrowserOptionsSlowMo(t *testing.T) { t.Parallel() tb := newTestBrowser(t, withFileServer()) testFrameSlowMoImpl(t, tb, func(_ *testBrowser, f *common.Frame) { - err := f.Hover("button", nil) + err := f.Hover("button", common.NewFrameHoverOptions(f.Timeout())) require.NoError(t, err) }) }) diff --git a/internal/js/modules/k6/browser/tests/locator_test.go b/internal/js/modules/k6/browser/tests/locator_test.go index 5e608c6c2d1..8125a5a61d4 100644 --- a/internal/js/modules/k6/browser/tests/locator_test.go +++ b/internal/js/modules/k6/browser/tests/locator_test.go @@ -77,13 +77,13 @@ func TestLocator(t *testing.T) { l := p.Locator("#inputText", nil) require.NoError(t, l.Fill(value, nil)) - inputValue, err := p.InputValue("#inputText", nil) + inputValue, err := p.InputValue("#inputText", common.NewFrameInputValueOptions(p.MainFrame().Timeout())) require.NoError(t, err) require.Equal(t, value, inputValue) err = l.Clear(common.NewFrameFillOptions(l.Timeout())) assert.NoError(t, err) - inputValue, err = p.InputValue("#inputText", nil) + inputValue, err = p.InputValue("#inputText", common.NewFrameInputValueOptions(p.MainFrame().Timeout())) require.NoError(t, err) assert.Equal(t, "", inputValue) }, @@ -128,7 +128,7 @@ func TestLocator(t *testing.T) { const value = "fill me up" lo := p.Locator("#inputText", nil) require.NoError(t, lo.Fill(value, nil)) - inputValue, err := p.InputValue("#inputText", nil) + inputValue, err := p.InputValue("#inputText", common.NewFrameInputValueOptions(p.MainFrame().Timeout())) require.NoError(t, err) require.Equal(t, value, inputValue) }, @@ -138,7 +138,7 @@ func TestLocator(t *testing.T) { const value = "fill me up" lo := p.Locator("textarea", nil) require.NoError(t, lo.Fill(value, nil)) - inputValue, err := p.InputValue("textarea", nil) + inputValue, err := p.InputValue("textarea", common.NewFrameInputValueOptions(p.MainFrame().Timeout())) require.NoError(t, err) require.Equal(t, value, inputValue) }, @@ -231,7 +231,7 @@ func TestLocator(t *testing.T) { "Press", func(_ *testBrowser, p *common.Page) { lo := p.Locator("#inputText", nil) require.NoError(t, lo.Press("x", nil)) - inputValue, err := p.InputValue("#inputText", nil) + inputValue, err := p.InputValue("#inputText", common.NewFrameInputValueOptions(p.MainFrame().Timeout())) require.NoError(t, err) require.Equal(t, "xsomething", inputValue) }, @@ -271,7 +271,7 @@ func TestLocator(t *testing.T) { "Type", func(_ *testBrowser, p *common.Page) { lo := p.Locator("#inputText", nil) require.NoError(t, lo.Type("real ", nil)) - inputValue, err := p.InputValue("#inputText", nil) + inputValue, err := p.InputValue("#inputText", common.NewFrameInputValueOptions(p.MainFrame().Timeout())) require.NoError(t, err) require.Equal(t, "real something", inputValue) }, diff --git a/internal/js/modules/k6/browser/tests/page_test.go b/internal/js/modules/k6/browser/tests/page_test.go index 111eb0ff4ae..de2c109d028 100644 --- a/internal/js/modules/k6/browser/tests/page_test.go +++ b/internal/js/modules/k6/browser/tests/page_test.go @@ -92,11 +92,13 @@ func TestPageEmulateMedia(t *testing.T) { tb := newTestBrowser(t) p := tb.NewPage(nil) - err := p.EmulateMedia(tb.toSobekValue(emulateMediaOpts{ + popts := common.NewPageEmulateMediaOptions(p) + require.NoError(t, popts.Parse(tb.context(), tb.toSobekValue(emulateMediaOpts{ Media: "print", ColorScheme: "dark", ReducedMotion: "reduce", - })) + }))) + err := p.EmulateMedia(popts) require.NoError(t, err) result, err := p.Evaluate(`() => matchMedia('print').matches`) @@ -395,7 +397,7 @@ func TestPageInnerHTML(t *testing.T) { p := newTestBrowser(t).NewPage(nil) err := p.SetContent(sampleHTML, nil) require.NoError(t, err) - innerHTML, err := p.InnerHTML("div", nil) + innerHTML, err := p.InnerHTML("div", common.NewFrameInnerHTMLOptions(p.MainFrame().Timeout())) require.NoError(t, err) assert.Equal(t, `Test
  1. One
`, innerHTML) }) @@ -408,7 +410,7 @@ func TestPageInnerHTML(t *testing.T) { tb := newTestBrowser(t) p := tb.NewPage(nil) - _, err := p.InnerHTML("", nil) + _, err := p.InnerHTML("", common.NewFrameInnerHTMLOptions(p.Context().Timeout())) require.ErrorContains(t, err, "The provided selector is empty") }) @@ -419,7 +421,9 @@ func TestPageInnerHTML(t *testing.T) { p := tb.NewPage(nil) err := p.SetContent(sampleHTML, nil) require.NoError(t, err) - _, err = p.InnerHTML("p", tb.toSobekValue(jsFrameBaseOpts{Timeout: "100"})) + popts := common.NewFrameInnerHTMLOptions(p.MainFrame().Timeout()) + require.NoError(t, popts.Parse(tb.vu.Context(), tb.toSobekValue(jsFrameBaseOpts{Timeout: "100"}))) + _, err = p.InnerHTML("p", popts) require.Error(t, err) }) } @@ -433,7 +437,7 @@ func TestPageInnerText(t *testing.T) { p := newTestBrowser(t).NewPage(nil) err := p.SetContent(sampleHTML, nil) require.NoError(t, err) - innerText, err := p.InnerText("div", nil) + innerText, err := p.InnerText("div", common.NewFrameInnerTextOptions(p.MainFrame().Timeout())) require.NoError(t, err) assert.Equal(t, "Test\nOne", innerText) }) @@ -443,7 +447,7 @@ func TestPageInnerText(t *testing.T) { tb := newTestBrowser(t) p := tb.NewPage(nil) - _, err := p.InnerText("", nil) + _, err := p.InnerText("", common.NewFrameInnerTextOptions(p.MainFrame().Timeout())) require.ErrorContains(t, err, "The provided selector is empty") }) @@ -454,7 +458,10 @@ func TestPageInnerText(t *testing.T) { p := tb.NewPage(nil) err := p.SetContent(sampleHTML, nil) require.NoError(t, err) - _, err = p.InnerText("p", tb.toSobekValue(jsFrameBaseOpts{Timeout: "100"})) + + popts := common.NewFrameInnerTextOptions(p.MainFrame().Timeout()) + require.NoError(t, popts.Parse(tb.vu.Context(), tb.toSobekValue(jsFrameBaseOpts{Timeout: "100"}))) + _, err = p.InnerText("p", popts) require.Error(t, err) }) } @@ -518,17 +525,17 @@ func TestPageInputValue(t *testing.T) { `, nil) require.NoError(t, err) - inputValue, err := p.InputValue("input", nil) + inputValue, err := p.InputValue("input", common.NewFrameInputValueOptions(p.MainFrame().Timeout())) require.NoError(t, err) got, want := inputValue, "hello1" assert.Equal(t, got, want) - inputValue, err = p.InputValue("select", nil) + inputValue, err = p.InputValue("select", common.NewFrameInputValueOptions(p.MainFrame().Timeout())) require.NoError(t, err) got, want = inputValue, "hello2" assert.Equal(t, got, want) - inputValue, err = p.InputValue("textarea", nil) + inputValue, err = p.InputValue("textarea", common.NewFrameInputValueOptions(p.MainFrame().Timeout())) require.NoError(t, err) got, want = inputValue, "hello3" assert.Equal(t, got, want) @@ -589,16 +596,16 @@ func TestPageFill(t *testing.T) { } for _, tt := range happy { t.Run("happy/"+tt.name, func(t *testing.T) { - err := p.Fill(tt.selector, tt.value, nil) + err := p.Fill(tt.selector, tt.value, common.NewFrameFillOptions(p.MainFrame().Timeout())) require.NoError(t, err) - inputValue, err := p.InputValue(tt.selector, nil) + inputValue, err := p.InputValue(tt.selector, common.NewFrameInputValueOptions(p.MainFrame().Timeout())) require.NoError(t, err) require.Equal(t, tt.value, inputValue) }) } for _, tt := range sad { t.Run("sad/"+tt.name, func(t *testing.T) { - err := p.Fill(tt.selector, tt.value, nil) + err := p.Fill(tt.selector, tt.value, common.NewFrameFillOptions(p.MainFrame().Timeout())) require.Error(t, err) }) } @@ -950,7 +957,7 @@ func TestPagePress(t *testing.T) { require.NoError(t, p.Press("#text1", "KeyB", nil)) require.NoError(t, p.Press("#text1", "Shift+KeyC", nil)) - inputValue, err := p.InputValue("#text1", nil) + inputValue, err := p.InputValue("#text1", common.NewFrameInputValueOptions(p.MainFrame().Timeout())) require.NoError(t, err) require.Equal(t, "AbC", inputValue) } @@ -989,7 +996,7 @@ func TestPageClose(t *testing.T) { p := b.NewPage(nil) - err := p.Close(nil) + err := p.Close() assert.NoError(t, err) }) @@ -1003,7 +1010,7 @@ func TestPageClose(t *testing.T) { p, err := c.NewPage() require.NoError(t, err) - err = p.Close(nil) + err = p.Close() assert.NoError(t, err) }) } @@ -1521,7 +1528,7 @@ func TestPageThrottleNetwork(t *testing.T) { _, err = page.WaitForSelector(selector, nil) require.NoError(t, err) - resp, err := page.InnerText(selector, nil) + resp, err := page.InnerText(selector, common.NewFrameInnerTextOptions(page.MainFrame().Timeout())) require.NoError(t, err) ms, err := strconv.ParseInt(resp, 10, 64) require.NoError(t, err) @@ -1857,7 +1864,7 @@ func TestPageTargetBlank(t *testing.T) { assert.Equal(t, 2, len(pp)) // Make sure the new page contains the correct page. - got, err := p2.InnerHTML("h1", nil) + got, err := p2.InnerHTML("h1", common.NewFrameInnerHTMLOptions(p.MainFrame().Timeout())) require.NoError(t, err) assert.Equal(t, "you clicked!", got) } @@ -1869,7 +1876,7 @@ func TestPageGetAttribute(t *testing.T) { err := p.SetContent(`Something`, nil) require.NoError(t, err) - got, ok, err := p.GetAttribute("#el", "href", nil) + got, ok, err := p.GetAttribute("#el", "href", common.NewFrameBaseOptions(p.MainFrame().Timeout())) require.NoError(t, err) require.True(t, ok) assert.Equal(t, "null", got) @@ -1882,7 +1889,7 @@ func TestPageGetAttributeMissing(t *testing.T) { err := p.SetContent(`Something`, nil) require.NoError(t, err) - got, ok, err := p.GetAttribute("#el", "missing", nil) + got, ok, err := p.GetAttribute("#el", "missing", common.NewFrameBaseOptions(p.MainFrame().Timeout())) require.NoError(t, err) require.False(t, ok) assert.Equal(t, "", got) @@ -1895,7 +1902,7 @@ func TestPageGetAttributeEmpty(t *testing.T) { err := p.SetContent(`Something`, nil) require.NoError(t, err) - got, ok, err := p.GetAttribute("#el", "empty", nil) + got, ok, err := p.GetAttribute("#el", "empty", common.NewFrameBaseOptions(p.MainFrame().Timeout())) require.NoError(t, err) require.True(t, ok) assert.Equal(t, "", got) diff --git a/internal/js/modules/k6/browser/tests/webvital_test.go b/internal/js/modules/k6/browser/tests/webvital_test.go index a9abf82fb09..7283a372b8e 100644 --- a/internal/js/modules/k6/browser/tests/webvital_test.go +++ b/internal/js/modules/k6/browser/tests/webvital_test.go @@ -83,7 +83,7 @@ func TestWebVitalMetric(t *testing.T) { require.NoError(t, err) // prevents `err:fetching response body: context canceled` warning.` - require.NoError(t, page.Close(nil)) + require.NoError(t, page.Close()) done <- struct{}{} for k, v := range expected { @@ -141,7 +141,7 @@ func TestWebVitalMetricNoInteraction(t *testing.T) { require.NotNil(t, resp) // prevents `err:fetching response body: context canceled` warning.` - require.NoError(t, page.Close(nil)) + require.NoError(t, page.Close()) done <- struct{}{} for k, v := range expected {