From 8244d497c339906f4a950bd0c3de68b408b6c4f4 Mon Sep 17 00:00:00 2001 From: ankur22 Date: Fri, 23 Aug 2024 09:45:31 +0100 Subject: [PATCH] Update to browser v1.7.1 Contains a good fix that would benefit users. --- go.mod | 2 +- go.sum | 4 +- .../browser/element_handle_mapping.go | 5 ++ .../xk6-browser/browser/frame_mapping.go | 5 ++ .../xk6-browser/browser/locator_mapping.go | 5 ++ .../xk6-browser/browser/page_mapping.go | 5 ++ .../grafana/xk6-browser/common/frame.go | 31 ++++++++++ .../xk6-browser/common/frame_session.go | 56 +++++++++++-------- .../grafana/xk6-browser/common/locator.go | 26 +++++++++ .../grafana/xk6-browser/common/page.go | 9 ++- vendor/modules.txt | 2 +- 11 files changed, 123 insertions(+), 27 deletions(-) diff --git a/go.mod b/go.mod index 50b03886e6f..e67e796844c 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/go-sourcemap/sourcemap v2.1.4+incompatible github.com/golang/protobuf v1.5.4 github.com/gorilla/websocket v1.5.1 - github.com/grafana/xk6-browser v1.7.0 + github.com/grafana/xk6-browser v1.7.1 github.com/grafana/xk6-dashboard v0.7.5 github.com/grafana/xk6-output-opentelemetry v0.1.1 github.com/grafana/xk6-output-prometheus-remote v0.4.0 diff --git a/go.sum b/go.sum index a040c7f4136..bf42e1e8a3d 100644 --- a/go.sum +++ b/go.sum @@ -84,8 +84,8 @@ github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/ github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= github.com/grafana/sobek v0.0.0-20240816075701-fd55381ddfc3 h1:mJ1DN6EDA5MlRtcspUjVTsfINUVJMd4Yw70RdFoKN8E= github.com/grafana/sobek v0.0.0-20240816075701-fd55381ddfc3/go.mod h1:14YTHWUwjApKs5kzRn+4akwbvPMRsXEmjfozc5OmT0I= -github.com/grafana/xk6-browser v1.7.0 h1:Rip0st43EmzV37DFO2Gt7sXO4TTRM4g9wGMwBvVb67c= -github.com/grafana/xk6-browser v1.7.0/go.mod h1:TNngUsbmV3I5NDVklGxjpAR2znEjYEsBtHQirGw8nAI= +github.com/grafana/xk6-browser v1.7.1 h1:RKCcoFyKT97iGgbnK76WwxcXnkB23ijlO1LghqjHQ0E= +github.com/grafana/xk6-browser v1.7.1/go.mod h1:sZO7cT7/XQf2mz+rXkp6poswhOCA0JKA8isj3fQrfaU= github.com/grafana/xk6-dashboard v0.7.5 h1:TcILyffT/Ea/XD7xG1jMA5lwtusOPRbEQsQDHmO30Mk= github.com/grafana/xk6-dashboard v0.7.5/go.mod h1:Y75F8xmgCraKT+pBzFH6me9AyH5PkXD+Bxo1dm6Il/M= github.com/grafana/xk6-output-opentelemetry v0.1.1 h1:kLfzKkL9olhmMO+Kmr7ObhX3LknSAbUbzFaDG6mQVeg= diff --git a/vendor/github.com/grafana/xk6-browser/browser/element_handle_mapping.go b/vendor/github.com/grafana/xk6-browser/browser/element_handle_mapping.go index c598ce739d2..e38a78bef87 100644 --- a/vendor/github.com/grafana/xk6-browser/browser/element_handle_mapping.go +++ b/vendor/github.com/grafana/xk6-browser/browser/element_handle_mapping.go @@ -171,6 +171,11 @@ func mapElementHandle(vu moduleVU, eh *common.ElementHandle) mapping { //nolint: return nil, eh.SelectText(opts) //nolint:wrapcheck }) }, + "setChecked": func(checked bool, opts sobek.Value) *sobek.Promise { + return k6ext.Promise(vu.Context(), func() (any, error) { + return nil, eh.SetChecked(checked, opts) //nolint:wrapcheck + }) + }, "setInputFiles": func(files sobek.Value, opts sobek.Value) *sobek.Promise { return k6ext.Promise(vu.Context(), func() (any, error) { return nil, eh.SetInputFiles(files, opts) //nolint:wrapcheck diff --git a/vendor/github.com/grafana/xk6-browser/browser/frame_mapping.go b/vendor/github.com/grafana/xk6-browser/browser/frame_mapping.go index 4d1aaf3a694..f300070ce2e 100644 --- a/vendor/github.com/grafana/xk6-browser/browser/frame_mapping.go +++ b/vendor/github.com/grafana/xk6-browser/browser/frame_mapping.go @@ -192,6 +192,11 @@ func mapFrame(vu moduleVU, f *common.Frame) mapping { //nolint:gocognit,cyclop return f.SelectOption(selector, values, opts) //nolint:wrapcheck }) }, + "setChecked": func(selector string, checked bool, opts sobek.Value) *sobek.Promise { + return k6ext.Promise(vu.Context(), func() (any, error) { + return nil, f.SetChecked(selector, checked, opts) //nolint:wrapcheck + }) + }, "setContent": func(html string, opts sobek.Value) *sobek.Promise { return k6ext.Promise(vu.Context(), func() (any, error) { return nil, f.SetContent(html, opts) //nolint:wrapcheck diff --git a/vendor/github.com/grafana/xk6-browser/browser/locator_mapping.go b/vendor/github.com/grafana/xk6-browser/browser/locator_mapping.go index 1df2f73ecdf..bc014da1cc9 100644 --- a/vendor/github.com/grafana/xk6-browser/browser/locator_mapping.go +++ b/vendor/github.com/grafana/xk6-browser/browser/locator_mapping.go @@ -36,6 +36,11 @@ func mapLocator(vu moduleVU, lo *common.Locator) mapping { //nolint:funlen return nil, lo.Dblclick(opts) //nolint:wrapcheck }) }, + "setChecked": func(checked bool, opts sobek.Value) *sobek.Promise { + return k6ext.Promise(vu.Context(), func() (any, error) { + return nil, lo.SetChecked(checked, opts) //nolint:wrapcheck + }) + }, "check": func(opts sobek.Value) *sobek.Promise { return k6ext.Promise(vu.Context(), func() (any, error) { return nil, lo.Check(opts) //nolint:wrapcheck diff --git a/vendor/github.com/grafana/xk6-browser/browser/page_mapping.go b/vendor/github.com/grafana/xk6-browser/browser/page_mapping.go index 5fadac70069..7703b8e8d77 100644 --- a/vendor/github.com/grafana/xk6-browser/browser/page_mapping.go +++ b/vendor/github.com/grafana/xk6-browser/browser/page_mapping.go @@ -263,6 +263,11 @@ func mapPage(vu moduleVU, p *common.Page) mapping { //nolint:gocognit,cyclop return p.SelectOption(selector, values, opts) //nolint:wrapcheck }) }, + "setChecked": func(selector string, checked bool, opts sobek.Value) *sobek.Promise { + return k6ext.Promise(vu.Context(), func() (any, error) { + return nil, p.SetChecked(selector, checked, opts) //nolint:wrapcheck + }) + }, "setContent": func(html string, opts sobek.Value) *sobek.Promise { return k6ext.Promise(vu.Context(), func() (any, error) { return nil, p.SetContent(html, opts) //nolint:wrapcheck diff --git a/vendor/github.com/grafana/xk6-browser/common/frame.go b/vendor/github.com/grafana/xk6-browser/common/frame.go index 6e2aa2365d2..8245ca54eac 100644 --- a/vendor/github.com/grafana/xk6-browser/common/frame.go +++ b/vendor/github.com/grafana/xk6-browser/common/frame.go @@ -645,6 +645,37 @@ func (f *Frame) check(selector string, opts *FrameCheckOptions) error { return nil } +func (f *Frame) setChecked(selector string, checked bool, opts *FrameCheckOptions) error { + setChecked := func(apiCtx context.Context, handle *ElementHandle, p *Position) (any, error) { + return nil, handle.setChecked(apiCtx, checked, p) + } + act := f.newPointerAction( + selector, DOMElementStateAttached, opts.Strict, setChecked, &opts.ElementHandleBasePointerOptions, + ) + if _, err := call(f.ctx, act, opts.Timeout); err != nil { + return errorFromDOMError(err) + } + + return nil +} + +// SetChecked sets the checked state of the first element found that matches the selector. +func (f *Frame) SetChecked(selector string, checked bool, opts sobek.Value) error { + f.log.Debugf("Frame:SetChecked", "fid:%s furl:%q sel:%q", f.ID(), f.URL(), selector) + + popts := NewFrameCheckOptions(f.defaultTimeout()) + if err := popts.Parse(f.ctx, opts); err != nil { + return fmt.Errorf("parsing frame set check options: %w", err) + } + if err := f.setChecked(selector, checked, popts); err != nil { + return fmt.Errorf("setting checked %q: %w", selector, err) + } + + applySlowMo(f.ctx) + + return nil +} + // Uncheck the first found element that matches the selector. func (f *Frame) Uncheck(selector string, opts sobek.Value) error { f.log.Debugf("Frame:Uncheck", "fid:%s furl:%q sel:%q", f.ID(), f.URL(), selector) diff --git a/vendor/github.com/grafana/xk6-browser/common/frame_session.go b/vendor/github.com/grafana/xk6-browser/common/frame_session.go index 8fb82115ea3..b7ae24a8a6c 100644 --- a/vendor/github.com/grafana/xk6-browser/common/frame_session.go +++ b/vendor/github.com/grafana/xk6-browser/common/frame_session.go @@ -57,7 +57,9 @@ type FrameSession struct { k6Metrics *k6ext.CustomMetrics targetID target.ID - windowID browser.WindowID + // windowID can be 0 when it is associated to an iframe or frame with no UI. + windowID browser.WindowID + hasUIWindow bool // To understand the concepts of Isolated Worlds, Contexts and Frames and // the relationship betwween them have a look at the following doc: @@ -82,7 +84,7 @@ type FrameSession struct { // //nolint:funlen func NewFrameSession( - ctx context.Context, s session, p *Page, parent *FrameSession, tid target.ID, l *log.Logger, + ctx context.Context, s session, p *Page, parent *FrameSession, tid target.ID, l *log.Logger, hasUIWindow bool, ) (_ *FrameSession, err error) { l.Debugf("NewFrameSession", "sid:%v tid:%v", s.ID(), tid) @@ -103,6 +105,7 @@ func NewFrameSession( vu: k6ext.GetVU(ctx), k6Metrics: k6Metrics, logger: l, + hasUIWindow: hasUIWindow, } if err := cdpruntime.RunIfWaitingForDebugger().Do(cdp.WithExecutor(fs.ctx, fs.session)); err != nil { @@ -120,14 +123,20 @@ func NewFrameSession( return nil, err } - action := browser.GetWindowForTarget().WithTargetID(fs.targetID) - if fs.windowID, _, err = action.Do(cdp.WithExecutor(fs.ctx, fs.session)); err != nil { - l.Debugf( - "NewFrameSession:GetWindowForTarget", - "sid:%v tid:%v err:%v", - s.ID(), tid, err) + // When a frame creates a new FrameSession without UI (e.g. some iframes) we cannot + // retrieve the windowID. Doing so would lead to an error from chromium. For now all + // iframes that are attached are setup with hasUIWindow as false which seems to work + // as expected for iframes with and without UI elements. + if fs.hasUIWindow { + action := browser.GetWindowForTarget().WithTargetID(fs.targetID) + if fs.windowID, _, err = action.Do(cdp.WithExecutor(fs.ctx, fs.session)); err != nil { + l.Debugf( + "NewFrameSession:GetWindowForTarget", + "sid:%v tid:%v err:%v", + s.ID(), tid, err) - return nil, fmt.Errorf("getting browser window ID: %w", err) + return nil, fmt.Errorf("getting browser window ID: %w", err) + } } fs.initEvents() @@ -994,7 +1003,8 @@ func (fs *FrameSession) attachIFrameToTarget(ti *target.Info, sid target.Session fs.ctx, fs.page.browserCtx.getSession(sid), fs.page, fs, ti.TargetID, - fs.logger) + fs.logger, + false) if err != nil { return fmt.Errorf("attaching iframe target ID %v to session ID %v: %w", ti.TargetID, sid, err) @@ -1187,18 +1197,20 @@ func (fs *FrameSession) updateViewport() error { return fmt.Errorf("emulating viewport: %w", err) } - // add an inset to viewport depending on the operating system. - // this won't add an inset if we're running in headless mode. - viewport.calculateInset( - fs.page.browserCtx.browser.browserOpts.Headless, - runtime.GOOS, - ) - action2 := browser.SetWindowBounds(fs.windowID, &browser.Bounds{ - Width: viewport.Width, - Height: viewport.Height, - }) - if err := action2.Do(cdp.WithExecutor(fs.ctx, fs.session)); err != nil { - return fmt.Errorf("setting window bounds: %w", err) + if fs.hasUIWindow { + // add an inset to viewport depending on the operating system. + // this won't add an inset if we're running in headless mode. + viewport.calculateInset( + fs.page.browserCtx.browser.browserOpts.Headless, + runtime.GOOS, + ) + action2 := browser.SetWindowBounds(fs.windowID, &browser.Bounds{ + Width: viewport.Width, + Height: viewport.Height, + }) + if err := action2.Do(cdp.WithExecutor(fs.ctx, fs.session)); err != nil { + return fmt.Errorf("setting window bounds: %w", err) + } } return nil diff --git a/vendor/github.com/grafana/xk6-browser/common/locator.go b/vendor/github.com/grafana/xk6-browser/common/locator.go index 89158ae62e9..3b49f3b5c93 100644 --- a/vendor/github.com/grafana/xk6-browser/common/locator.go +++ b/vendor/github.com/grafana/xk6-browser/common/locator.go @@ -104,6 +104,32 @@ func (l *Locator) dblclick(opts *FrameDblclickOptions) error { return l.frame.dblclick(l.selector, opts) } +// SetChecked sets the checked state of the element using locator's selector +// with strict mode on. +func (l *Locator) SetChecked(checked bool, opts sobek.Value) error { + l.log.Debugf( + "Locator:SetChecked", "fid:%s furl:%q sel:%q checked:%v opts:%+v", + l.frame.ID(), l.frame.URL(), l.selector, checked, opts, + ) + + copts := NewFrameCheckOptions(l.frame.defaultTimeout()) + if err := copts.Parse(l.ctx, opts); err != nil { + return fmt.Errorf("parsing set checked options: %w", err) + } + if err := l.setChecked(checked, copts); err != nil { + return fmt.Errorf("setting %q checked to %v: %w", l.selector, checked, err) + } + + applySlowMo(l.ctx) + + return nil +} + +func (l *Locator) setChecked(checked bool, opts *FrameCheckOptions) error { + opts.Strict = true + return l.frame.setChecked(l.selector, checked, opts) +} + // Check on an element using locator's selector with strict mode on. func (l *Locator) Check(opts sobek.Value) error { l.log.Debugf("Locator:Check", "fid:%s furl:%q sel:%q opts:%+v", l.frame.ID(), l.frame.URL(), l.selector, opts) diff --git a/vendor/github.com/grafana/xk6-browser/common/page.go b/vendor/github.com/grafana/xk6-browser/common/page.go index 35b2f296ed0..1c2b96394c8 100644 --- a/vendor/github.com/grafana/xk6-browser/common/page.go +++ b/vendor/github.com/grafana/xk6-browser/common/page.go @@ -296,7 +296,7 @@ func NewPage( var err error p.frameManager = NewFrameManager(ctx, s, &p, p.timeoutSettings, p.logger) - p.mainFrameSession, err = NewFrameSession(ctx, s, &p, nil, tid, p.logger) + p.mainFrameSession, err = NewFrameSession(ctx, s, &p, nil, tid, p.logger, true) if err != nil { p.logger.Debugf("Page:NewPage:NewFrameSession:return", "sid:%v tid:%v err:%v", p.sessionID(), tid, err) @@ -628,6 +628,13 @@ func (p *Page) BringToFront() error { return nil } +// SetChecked sets the checked state of the element matching the provided selector. +func (p *Page) SetChecked(selector string, checked bool, opts sobek.Value) error { + p.logger.Debugf("Page:SetChecked", "sid:%v selector:%s checked:%t", p.sessionID(), selector, checked) + + return p.MainFrame().SetChecked(selector, checked, opts) +} + // Check checks an element matching the provided selector. func (p *Page) Check(selector string, opts sobek.Value) error { p.logger.Debugf("Page:Check", "sid:%v selector:%s", p.sessionID(), selector) diff --git a/vendor/modules.txt b/vendor/modules.txt index 5ddb8297f03..1305094bd56 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -173,7 +173,7 @@ github.com/grafana/sobek/ftoa/internal/fast github.com/grafana/sobek/parser github.com/grafana/sobek/token github.com/grafana/sobek/unistring -# github.com/grafana/xk6-browser v1.7.0 +# github.com/grafana/xk6-browser v1.7.1 ## explicit; go 1.20 github.com/grafana/xk6-browser/browser github.com/grafana/xk6-browser/chromium