Skip to content
This repository has been archived by the owner on Jan 30, 2025. It is now read-only.

Refactor Sobek out of screenshots and byte pointer changes #1198

Merged
merged 5 commits into from
Jan 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 33 additions & 4 deletions browser/mapping.go
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ func mapJSHandle(vu moduleVU, jsh common.JSHandleAPI) mapping {
//
//nolint:funlen
func mapElementHandle(vu moduleVU, eh *common.ElementHandle) mapping {
rt := vu.Runtime()
maps := mapping{
"boundingBox": eh.BoundingBox,
"check": eh.Check,
Expand Down Expand Up @@ -280,8 +281,22 @@ func mapElementHandle(vu moduleVU, eh *common.ElementHandle) mapping {
return mapFrame(vu, f), nil
},
"press": eh.Press,
"screenshot": func(opts goja.Value) goja.ArrayBuffer {
return eh.Screenshot(opts, vu.LocalFilePersister)
"screenshot": func(opts goja.Value) (*goja.ArrayBuffer, error) {
ctx := vu.Context()

popts := common.NewElementHandleScreenshotOptions(eh.Timeout())
if err := popts.Parse(ctx, opts); err != nil {
return nil, fmt.Errorf("parsing frame screenshot options: %w", err)
}

bb, err := eh.Screenshot(popts, vu.LocalFilePersister)
if err != nil {
return nil, err //nolint:wrapcheck
}

ab := rt.NewArrayBuffer(bb)

return &ab, nil
},
"scrollIntoViewIfNeeded": eh.ScrollIntoViewIfNeeded,
"selectOption": eh.SelectOption,
Expand Down Expand Up @@ -689,8 +704,22 @@ func mapPage(vu moduleVU, p *common.Page) mapping {
return rt.ToValue(r).ToObject(rt)
},
"route": p.Route,
"screenshot": func(opts goja.Value) goja.ArrayBuffer {
return p.Screenshot(opts, vu.LocalFilePersister)
"screenshot": func(opts goja.Value) (*goja.ArrayBuffer, error) {
ctx := vu.Context()

popts := common.NewPageScreenshotOptions()
if err := popts.Parse(ctx, opts); err != nil {
return nil, fmt.Errorf("parsing page screenshot options: %w", err)
}

bb, err := p.Screenshot(popts, vu.LocalFilePersister)
if err != nil {
return nil, err //nolint:wrapcheck
}

ab := rt.NewArrayBuffer(bb)

return &ab, nil
},
"selectOption": p.SelectOption,
"setContent": p.SetContent,
Expand Down
19 changes: 9 additions & 10 deletions common/element_handle.go
Original file line number Diff line number Diff line change
Expand Up @@ -1178,27 +1178,26 @@ func (h *ElementHandle) setChecked(apiCtx context.Context, checked bool, p *Posi
}

// Screenshot will instruct Chrome to save a screenshot of the current element and save it to specified file.
func (h *ElementHandle) Screenshot(opts goja.Value, fp *storage.LocalFilePersister) goja.ArrayBuffer {
func (h *ElementHandle) Screenshot(
opts *ElementHandleScreenshotOptions,
fp *storage.LocalFilePersister,
) ([]byte, error) {
spanCtx, span := TraceAPICall(
h.ctx,
h.frame.page.targetID.String(),
"elementHandle.screenshot",
)
defer span.End()

rt := h.execCtx.vu.Runtime()
parsedOpts := NewElementHandleScreenshotOptions(h.defaultTimeout())
if err := parsedOpts.Parse(h.ctx, opts); err != nil {
k6ext.Panic(h.ctx, "parsing screenshot options: %w", err)
}
span.SetAttributes(attribute.String("screenshot.path", parsedOpts.Path))
span.SetAttributes(attribute.String("screenshot.path", opts.Path))

s := newScreenshotter(spanCtx, fp)
buf, err := s.screenshotElement(h, parsedOpts)
buf, err := s.screenshotElement(h, opts)
if err != nil {
k6ext.Panic(h.ctx, "taking screenshot: %w", err)
return nil, fmt.Errorf("taking screenshot of elementHandle: %w", err)
}
return rt.NewArrayBuffer(*buf)

return buf, err
}

func (h *ElementHandle) ScrollIntoViewIfNeeded(opts goja.Value) {
Expand Down
16 changes: 6 additions & 10 deletions common/page.go
Original file line number Diff line number Diff line change
Expand Up @@ -1121,23 +1121,19 @@ func (p *Page) Route(url goja.Value, handler goja.Callable) {
}

// Screenshot will instruct Chrome to save a screenshot of the current page and save it to specified file.
func (p *Page) Screenshot(opts goja.Value, fp *storage.LocalFilePersister) goja.ArrayBuffer {
func (p *Page) Screenshot(opts *PageScreenshotOptions, fp *storage.LocalFilePersister) ([]byte, error) {
spanCtx, span := TraceAPICall(p.ctx, p.targetID.String(), "page.screenshot")
defer span.End()

parsedOpts := NewPageScreenshotOptions()
if err := parsedOpts.Parse(p.ctx, opts); err != nil {
k6ext.Panic(p.ctx, "parsing screenshot options: %w", err)
}
span.SetAttributes(attribute.String("screenshot.path", parsedOpts.Path))
span.SetAttributes(attribute.String("screenshot.path", opts.Path))

s := newScreenshotter(spanCtx, fp)
buf, err := s.screenshotPage(p, parsedOpts)
buf, err := s.screenshotPage(p, opts)
if err != nil {
k6ext.Panic(p.ctx, "capturing screenshot: %w", err)
return nil, fmt.Errorf("taking screenshot of page: %w", err)
}
rt := p.vu.Runtime()
return rt.NewArrayBuffer(*buf)

return buf, err
}

func (p *Page) SelectOption(selector string, values goja.Value, opts goja.Value) []string {
Expand Down
35 changes: 20 additions & 15 deletions common/screenshotter.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
"github.com/chromedp/cdproto/cdp"
"github.com/chromedp/cdproto/emulation"
cdppage "github.com/chromedp/cdproto/page"
"github.com/dop251/goja"

"github.com/grafana/xk6-browser/storage"
)
Expand Down Expand Up @@ -121,12 +120,14 @@ func (s *screenshotter) originalViewportSize(p *Page) (*Size, *Size, error) {
if err != nil {
return nil, nil, fmt.Errorf("getting viewport dimensions: %w", err)
}
r, ok := result.(goja.Object)
if !ok {
return nil, nil, fmt.Errorf("cannot convert to goja object: %w", err)

var returnVal Size
if err := convert(result, &returnVal); err != nil {
return nil, nil, fmt.Errorf("unpacking window size: %w", err)
}
viewportSize.Width = r.Get("width").ToFloat()
viewportSize.Height = r.Get("height").ToFloat()

viewportSize.Width = returnVal.Width
viewportSize.Height = returnVal.Height

return &viewportSize, &originalViewportSize, nil
}
Expand All @@ -141,7 +142,7 @@ func (s *screenshotter) restoreViewport(p *Page, originalViewport *Size) error {
//nolint:funlen,cyclop
func (s *screenshotter) screenshot(
sess session, doc, viewport *Rect, format ImageFormat, omitBackground bool, quality int64, path string,
) (*[]byte, error) {
) ([]byte, error) {
var (
buf []byte
clip *cdppage.Viewport
Expand Down Expand Up @@ -222,10 +223,11 @@ func (s *screenshotter) screenshot(
}
}

return &buf, nil
return buf, nil
}

func (s *screenshotter) screenshotElement(h *ElementHandle, opts *ElementHandleScreenshotOptions) (*[]byte, error) {
//nolint:funlen,cyclop
func (s *screenshotter) screenshotElement(h *ElementHandle, opts *ElementHandleScreenshotOptions) ([]byte, error) {
format := opts.Format
viewportSize, originalViewportSize, err := s.originalViewportSize(h.frame.page)
if err != nil {
Expand Down Expand Up @@ -276,14 +278,16 @@ func (s *screenshotter) screenshotElement(h *ElementHandle, opts *ElementHandleS
}

documentRect := bbox
rt := h.execCtx.vu.Runtime()
scrollOffset := h.Evaluate(`() => { return {x: window.scrollX, y: window.scrollY};}`)
switch s := scrollOffset.(type) {
case goja.Value:
documentRect.X += s.ToObject(rt).Get("x").ToFloat()
documentRect.Y += s.ToObject(rt).Get("y").ToFloat()

var returnVal Position
if err := convert(scrollOffset, &returnVal); err != nil {
return nil, fmt.Errorf("unpacking scroll offset: %w", err)
}

documentRect.X += returnVal.X
documentRect.Y += returnVal.Y

buf, err := s.screenshot(h.frame.page.session, documentRect.enclosingIntRect(), nil, format, opts.OmitBackground, opts.Quality, opts.Path)
if err != nil {
return nil, err
Expand All @@ -296,7 +300,8 @@ func (s *screenshotter) screenshotElement(h *ElementHandle, opts *ElementHandleS
return buf, nil
}

func (s *screenshotter) screenshotPage(p *Page, opts *PageScreenshotOptions) (*[]byte, error) {
//nolint:funlen,cyclop,gocognit
ankur22 marked this conversation as resolved.
Show resolved Hide resolved
func (s *screenshotter) screenshotPage(p *Page, opts *PageScreenshotOptions) ([]byte, error) {
format := opts.Format

// Infer file format by path
Expand Down
8 changes: 6 additions & 2 deletions tests/element_handle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -375,9 +375,13 @@ func TestElementHandleScreenshot(t *testing.T) {
elem, err := p.Query("div")
require.NoError(t, err)

buf := elem.Screenshot(nil, &storage.LocalFilePersister{})
buf, err := elem.Screenshot(
common.NewElementHandleScreenshotOptions(elem.Timeout()),
&storage.LocalFilePersister{},
)
require.NoError(t, err)

reader := bytes.NewReader(buf.Bytes())
reader := bytes.NewReader(buf)
img, err := png.Decode(reader)
assert.Nil(t, err)

Expand Down
11 changes: 5 additions & 6 deletions tests/page_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -474,13 +474,12 @@ func TestPageScreenshotFullpage(t *testing.T) {
}
`)

buf := p.Screenshot(tb.toGojaValue(struct {
FullPage bool `js:"fullPage"`
}{
FullPage: true,
}), &storage.LocalFilePersister{})
opts := common.NewPageScreenshotOptions()
opts.FullPage = true
buf, err := p.Screenshot(opts, &storage.LocalFilePersister{})
require.NoError(t, err)

reader := bytes.NewReader(buf.Bytes())
reader := bytes.NewReader(buf)
img, err := png.Decode(reader)
assert.Nil(t, err)

Expand Down
Loading