diff --git a/internal/js/modules/k6/browser/browser/frame_mapping.go b/internal/js/modules/k6/browser/browser/frame_mapping.go index cb2a20e91ef..8daaa9f7c43 100644 --- a/internal/js/modules/k6/browser/browser/frame_mapping.go +++ b/internal/js/modules/k6/browser/browser/frame_mapping.go @@ -245,10 +245,14 @@ func mapFrame(vu moduleVU, f *common.Frame) mapping { "parentFrame": func() mapping { return mapFrame(vu, f.ParentFrame()) }, - "press": func(selector, key string, opts sobek.Value) *sobek.Promise { + "press": func(selector, key string, opts sobek.Value) (*sobek.Promise, error) { + popts := common.NewFramePressOptions(f.Timeout()) + if err := popts.Parse(vu.Context(), opts); err != nil { + return nil, fmt.Errorf("parse press options of selector %q on key %q: %w", selector, key, err) + } return k6ext.Promise(vu.Context(), func() (any, error) { - return nil, f.Press(selector, key, opts) //nolint:wrapcheck - }) + return nil, f.Press(selector, key, popts) //nolint:wrapcheck + }), nil }, "selectOption": func(selector string, values sobek.Value, opts sobek.Value) (*sobek.Promise, error) { popts := common.NewFrameSelectOptionOptions(f.Timeout()) @@ -271,10 +275,14 @@ func mapFrame(vu moduleVU, f *common.Frame) mapping { return nil, f.SetChecked(selector, checked, popts) //nolint:wrapcheck }), nil }, - "setContent": func(html string, opts sobek.Value) *sobek.Promise { + "setContent": func(html string, opts sobek.Value) (*sobek.Promise, error) { + popts := common.NewFrameSetContentOptions(f.Page().NavigationTimeout()) + if err := popts.Parse(vu.Context(), opts); err != nil { + return nil, fmt.Errorf("parsing setContent options: %w", err) + } return k6ext.Promise(vu.Context(), func() (any, error) { - return nil, f.SetContent(html, opts) //nolint:wrapcheck - }) + return nil, f.SetContent(html, popts) //nolint:wrapcheck + }), nil }, "setInputFiles": func(selector string, files sobek.Value, opts sobek.Value) (*sobek.Promise, error) { popts := common.NewFrameSetInputFilesOptions(f.Timeout()) diff --git a/internal/js/modules/k6/browser/browser/page_mapping.go b/internal/js/modules/k6/browser/browser/page_mapping.go index 9078b7fcf75..6ebec58a1e7 100644 --- a/internal/js/modules/k6/browser/browser/page_mapping.go +++ b/internal/js/modules/k6/browser/browser/page_mapping.go @@ -285,26 +285,30 @@ func mapPage(vu moduleVU, p *common.Page) mapping { //nolint:gocognit,cyclop return p.Opener(), nil }) }, - "press": func(selector string, key string, opts sobek.Value) *sobek.Promise { + "press": func(selector string, key string, opts sobek.Value) (*sobek.Promise, error) { + popts := common.NewFramePressOptions(p.Timeout()) + if err := popts.Parse(vu.Context(), opts); err != nil { + return nil, fmt.Errorf("parsing press options of selector %q: %w", selector, err) + } return k6ext.Promise(vu.Context(), func() (any, error) { - // TODO(@mstoykov): don't use sobek Values in a separate goroutine - return nil, p.Press(selector, key, opts) //nolint:wrapcheck - }) + return nil, p.Press(selector, key, popts) //nolint:wrapcheck + }), nil }, - "reload": func(opts sobek.Value) *sobek.Promise { + "reload": func(opts sobek.Value) (*sobek.Promise, error) { + popts := common.NewPageReloadOptions(common.LifecycleEventLoad, p.NavigationTimeout()) + if err := popts.Parse(vu.Context(), opts); err != nil { + return nil, fmt.Errorf("parsing reload options: %w", err) + } return k6ext.Promise(vu.Context(), func() (any, error) { - // TODO(@mstoykov): don't use sobek Values in a separate goroutine - resp, err := p.Reload(opts) + resp, err := p.Reload(popts) if err != nil { return nil, err //nolint:wrapcheck } - if resp == nil { - return nil, nil + return nil, nil //nolint:nilnil } - return mapResponse(vu, resp), nil - }) + }), nil }, "screenshot": func(opts sobek.Value) (*sobek.Promise, error) { popts := common.NewPageScreenshotOptions() @@ -345,11 +349,14 @@ func mapPage(vu moduleVU, p *common.Page) mapping { //nolint:gocognit,cyclop return nil, p.SetChecked(selector, checked, popts) //nolint:wrapcheck }), nil }, - "setContent": func(html string, opts sobek.Value) *sobek.Promise { + "setContent": func(html string, opts sobek.Value) (*sobek.Promise, error) { + popts := common.NewFrameSetContentOptions(p.MainFrame().NavigationTimeout()) + if err := popts.Parse(vu.Context(), opts); err != nil { + return nil, fmt.Errorf("parsing setContent 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.SetContent(html, opts) //nolint:wrapcheck - }) + return nil, p.SetContent(html, popts) //nolint:wrapcheck + }), nil }, "setDefaultNavigationTimeout": p.SetDefaultNavigationTimeout, "setDefaultTimeout": p.SetDefaultTimeout, diff --git a/internal/js/modules/k6/browser/common/frame.go b/internal/js/modules/k6/browser/common/frame.go index e759e1ad0ed..38e6d3bc038 100644 --- a/internal/js/modules/k6/browser/common/frame.go +++ b/internal/js/modules/k6/browser/common/frame.go @@ -1391,14 +1391,10 @@ func (f *Frame) ParentFrame() *Frame { } // Press presses the given key for the first element found that matches the selector. -func (f *Frame) Press(selector, key string, opts sobek.Value) error { +func (f *Frame) Press(selector, key string, opts *FramePressOptions) error { f.log.Debugf("Frame:Press", "fid:%s furl:%q sel:%q key:%q", f.ID(), f.URL(), selector, key) - popts := NewFramePressOptions(f.defaultTimeout()) - if err := popts.Parse(f.ctx, opts); err != nil { - return fmt.Errorf("parsing press options: %w", err) - } - if err := f.press(selector, key, popts); err != nil { + if err := f.press(selector, key, opts); err != nil { return fmt.Errorf("pressing %q on %q: %w", key, selector, err) } @@ -1478,16 +1474,9 @@ func (f *Frame) selectOption(selector string, values sobek.Value, opts *FrameSel } // SetContent replaces the entire HTML document content. -func (f *Frame) SetContent(html string, opts sobek.Value) error { +func (f *Frame) SetContent(html string, _ *FrameSetContentOptions) error { f.log.Debugf("Frame:SetContent", "fid:%s furl:%q", f.ID(), f.URL()) - parsedOpts := NewFrameSetContentOptions( - f.manager.timeoutSettings.navigationTimeout(), - ) - if err := parsedOpts.Parse(f.ctx, opts); err != nil { - return fmt.Errorf("parsing set content options: %w", err) - } - js := `(html) => { window.stop(); document.open(); diff --git a/internal/js/modules/k6/browser/common/page.go b/internal/js/modules/k6/browser/common/page.go index 5cab4316cbb..c569ae0c9f3 100644 --- a/internal/js/modules/k6/browser/common/page.go +++ b/internal/js/modules/k6/browser/common/page.go @@ -1192,7 +1192,7 @@ func (p *Page) Opener() *Page { } // Press presses the given key for the first element found that matches the selector. -func (p *Page) Press(selector string, key string, opts sobek.Value) error { +func (p *Page) Press(selector string, key string, opts *FramePressOptions) error { p.logger.Debugf("Page:Press", "sid:%v selector:%s", p.sessionID(), selector) return p.MainFrame().Press(selector, key, opts) @@ -1213,22 +1213,12 @@ func (p *Page) QueryAll(selector string) ([]*ElementHandle, error) { } // Reload will reload the current page. -func (p *Page) Reload(opts sobek.Value) (*Response, error) { //nolint:funlen +func (p *Page) Reload(opts *PageReloadOptions) (*Response, error) { //nolint:funlen p.logger.Debugf("Page:Reload", "sid:%v", p.sessionID()) _, span := TraceAPICall(p.ctx, p.targetID.String(), "page.reload") defer span.End() - reloadOpts := NewPageReloadOptions( - LifecycleEventLoad, - p.timeoutSettings.navigationTimeout(), - ) - if err := reloadOpts.Parse(p.ctx, opts); err != nil { - err := fmt.Errorf("parsing reload options: %w", err) - spanRecordError(span, err) - return nil, err - } - - timeoutCtx, timeoutCancelFn := context.WithTimeout(p.ctx, reloadOpts.Timeout) + timeoutCtx, timeoutCancelFn := context.WithTimeout(p.ctx, opts.Timeout) defer timeoutCancelFn() waitForFrameNavigation, cancelWaitingForFrameNavigation := createWaitForEventHandler( @@ -1245,7 +1235,7 @@ func (p *Page) Reload(opts sobek.Value) (*Response, error) { //nolint:funlen []string{EventFrameAddLifecycle}, func(data any) bool { if le, ok := data.(FrameLifecycleEvent); ok { - return le.Event == reloadOpts.WaitUntil + return le.Event == opts.WaitUntil } return false }) @@ -1262,7 +1252,7 @@ func (p *Page) Reload(opts sobek.Value) (*Response, error) { //nolint:funlen if errors.Is(err, context.DeadlineExceeded) { err = &k6ext.UserFriendlyError{ Err: err, - Timeout: reloadOpts.Timeout, + Timeout: opts.Timeout, } return fmt.Errorf("reloading page: %w", err) } @@ -1342,7 +1332,7 @@ func (p *Page) SelectOption(selector string, values sobek.Value, popts *FrameSel } // SetContent replaces the entire HTML document content. -func (p *Page) SetContent(html string, opts sobek.Value) error { +func (p *Page) SetContent(html string, opts *FrameSetContentOptions) error { p.logger.Debugf("Page:SetContent", "sid:%v", p.sessionID()) return p.MainFrame().SetContent(html, opts) diff --git a/internal/js/modules/k6/browser/tests/frame_test.go b/internal/js/modules/k6/browser/tests/frame_test.go index 7108f6defb5..fad023b87ed 100644 --- a/internal/js/modules/k6/browser/tests/frame_test.go +++ b/internal/js/modules/k6/browser/tests/frame_test.go @@ -28,9 +28,10 @@ func TestFramePress(t *testing.T) { f := p.Frames()[0] - require.NoError(t, f.Press("#text1", "Shift+KeyA", nil)) - require.NoError(t, f.Press("#text1", "KeyB", nil)) - require.NoError(t, f.Press("#text1", "Shift+KeyC", nil)) + opts := common.NewFramePressOptions(f.Timeout()) + require.NoError(t, f.Press("#text1", "Shift+KeyA", opts)) + require.NoError(t, f.Press("#text1", "KeyB", opts)) + require.NoError(t, f.Press("#text1", "Shift+KeyC", opts)) inputValue, err := f.InputValue("#text1", common.NewFrameInputValueOptions(p.MainFrame().Timeout())) require.NoError(t, err) 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 20b8302466f..4f5751e450b 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 @@ -122,7 +122,7 @@ func TestBrowserOptionsSlowMo(t *testing.T) { t.Parallel() tb := newTestBrowser(t, withFileServer()) testPageSlowMoImpl(t, tb, func(_ *testBrowser, p *common.Page) { - err := p.Press("button", "Enter", nil) + err := p.Press("button", "Enter", common.NewFramePressOptions(p.MainFrame().Timeout())) require.NoError(t, err) }) }) @@ -130,7 +130,8 @@ func TestBrowserOptionsSlowMo(t *testing.T) { t.Parallel() tb := newTestBrowser(t, withFileServer()) testPageSlowMoImpl(t, tb, func(_ *testBrowser, p *common.Page) { - _, err := p.Reload(nil) + opts := common.NewPageReloadOptions(common.LifecycleEventLoad, p.MainFrame().NavigationTimeout()) + _, err := p.Reload(opts) require.NoError(t, err) }) }) @@ -262,7 +263,7 @@ func TestBrowserOptionsSlowMo(t *testing.T) { t.Parallel() tb := newTestBrowser(t, withFileServer()) testFrameSlowMoImpl(t, tb, func(_ *testBrowser, f *common.Frame) { - err := f.Press("button", "Enter", nil) + err := f.Press("button", "Enter", common.NewFramePressOptions(f.Timeout())) require.NoError(t, err) }) }) diff --git a/internal/js/modules/k6/browser/tests/lifecycle_wait_test.go b/internal/js/modules/k6/browser/tests/lifecycle_wait_test.go index 6e97a878af9..51762905986 100644 --- a/internal/js/modules/k6/browser/tests/lifecycle_wait_test.go +++ b/internal/js/modules/k6/browser/tests/lifecycle_wait_test.go @@ -415,10 +415,10 @@ func TestLifecycleReload(t *testing.T) { } tt.pingJSTextAssert(result) - opts := tb.toSobekValue(common.PageReloadOptions{ + opts := &common.PageReloadOptions{ WaitUntil: tt.waitUntil, Timeout: 30 * time.Second, - }) + } _, err = p.Reload(opts) require.NoError(t, err) diff --git a/internal/js/modules/k6/browser/tests/page_test.go b/internal/js/modules/k6/browser/tests/page_test.go index 92205981f09..2263e8c4f35 100644 --- a/internal/js/modules/k6/browser/tests/page_test.go +++ b/internal/js/modules/k6/browser/tests/page_test.go @@ -961,9 +961,10 @@ func TestPagePress(t *testing.T) { err := p.SetContent(``, nil) require.NoError(t, err) - require.NoError(t, p.Press("#text1", "Shift+KeyA", nil)) - require.NoError(t, p.Press("#text1", "KeyB", nil)) - require.NoError(t, p.Press("#text1", "Shift+KeyC", nil)) + opts := common.NewFramePressOptions(p.MainFrame().Timeout()) + require.NoError(t, p.Press("#text1", "Shift+KeyA", opts)) + require.NoError(t, p.Press("#text1", "KeyB", opts)) + require.NoError(t, p.Press("#text1", "Shift+KeyC", opts)) inputValue, err := p.InputValue("#text1", common.NewFrameInputValueOptions(p.MainFrame().Timeout())) require.NoError(t, err)