Skip to content

Commit

Permalink
Desobekify BrowserContextOptionParsing
Browse files Browse the repository at this point in the history
Moves the Sobek-dependent option parsing part out of the business logic.

Once we finish, we can entirely remove the Sobek dependency.
  • Loading branch information
inancgumus committed Nov 5, 2024
1 parent 2303d9c commit 946e4cb
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 144 deletions.
42 changes: 42 additions & 0 deletions browser/browser_context_options_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package browser

import (
"testing"

"github.com/stretchr/testify/assert"

"github.com/grafana/xk6-browser/common"
"github.com/grafana/xk6-browser/k6ext/k6test"
)

func TestBrowserContextOptionsPermissions(t *testing.T) {
vu := k6test.NewVU(t)

opts, err := parseBrowserContextOptions(vu.Context(), vu.ToSobekValue((struct {
Permissions []any `js:"permissions"`
}{
Permissions: []any{"camera", "microphone"},
})))
assert.NoError(t, err)
assert.Len(t, opts.Permissions, 2)
assert.Equal(t, opts.Permissions, []string{"camera", "microphone"})
}

func TestBrowserContextSetGeolocation(t *testing.T) {
vu := k6test.NewVU(t)

opts, err := parseBrowserContextOptions(vu.Context(), vu.ToSobekValue((struct {
GeoLocation *common.Geolocation `js:"geolocation"`
}{
GeoLocation: &common.Geolocation{
Latitude: 1.0,
Longitude: 2.0,
Accuracy: 3.0,
},
})))
assert.NoError(t, err)
assert.NotNil(t, opts)
assert.Equal(t, 1.0, opts.Geolocation.Latitude)
assert.Equal(t, 2.0, opts.Geolocation.Longitude)
assert.Equal(t, 3.0, opts.Geolocation.Accuracy)
}
102 changes: 98 additions & 4 deletions browser/browser_mapping.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package browser

import (
"context"
"fmt"

"github.com/grafana/sobek"
Expand Down Expand Up @@ -36,8 +37,8 @@ func mapBrowser(vu moduleVU) mapping { //nolint:funlen,cyclop,gocognit
return b.IsConnected(), nil
},
"newContext": func(opts sobek.Value) (*sobek.Promise, error) {
popts := common.NewBrowserContextOptions()
if err := popts.Parse(vu.Context(), opts); err != nil {
popts, err := parseBrowserContextOptions(vu.Context(), opts)
if err != nil {
return nil, fmt.Errorf("parsing browser.newContext options: %w", err)
}
return k6ext.Promise(vu.Context(), func() (any, error) {
Expand Down Expand Up @@ -71,8 +72,8 @@ func mapBrowser(vu moduleVU) mapping { //nolint:funlen,cyclop,gocognit
return b.Version(), nil
},
"newPage": func(opts sobek.Value) (*sobek.Promise, error) {
popts := common.NewBrowserContextOptions()
if err := popts.Parse(vu.Context(), opts); err != nil {
popts, err := parseBrowserContextOptions(vu.Context(), opts)
if err != nil {
return nil, fmt.Errorf("parsing browser.newPage options: %w", err)
}
return k6ext.Promise(vu.Context(), func() (any, error) {
Expand Down Expand Up @@ -107,3 +108,96 @@ func initBrowserContext(bctx *common.BrowserContext, testRunID string) error {

return nil
}

// parseBrowserContextOptions parses the [common.BrowserContext] options from a Sobek value.
func parseBrowserContextOptions(ctx context.Context, opts sobek.Value) (*common.BrowserContextOptions, error) { //nolint:cyclop,funlen,gocognit,lll
if !sobekValueExists(opts) {
return nil, nil //nolint:nilnil
}

b := common.NewBrowserContextOptions()

rt := k6ext.Runtime(ctx)
o := opts.ToObject(rt)
for _, k := range o.Keys() {
switch k {
case "acceptDownloads":
b.AcceptDownloads = o.Get(k).ToBoolean()
case "downloadsPath":
b.DownloadsPath = o.Get(k).String()
case "bypassCSP":
b.BypassCSP = o.Get(k).ToBoolean()
case "colorScheme":
switch common.ColorScheme(o.Get(k).String()) { //nolint:exhaustive
case "light":
b.ColorScheme = common.ColorSchemeLight
case "dark":
b.ColorScheme = common.ColorSchemeDark
default:
b.ColorScheme = common.ColorSchemeNoPreference
}
case "deviceScaleFactor":
b.DeviceScaleFactor = o.Get(k).ToFloat()
case "extraHTTPHeaders":
headers := o.Get(k).ToObject(rt)
for _, k := range headers.Keys() {
b.ExtraHTTPHeaders[k] = headers.Get(k).String()
}
case "geolocation":
geolocation := common.NewGeolocation()
if err := geolocation.Parse(ctx, o.Get(k).ToObject(rt)); err != nil {
return nil, fmt.Errorf("parsing geolocation options: %w", err)
}
b.Geolocation = geolocation
case "hasTouch":
b.HasTouch = o.Get(k).ToBoolean()
case "httpCredentials":
credentials := common.NewCredentials()
if err := credentials.Parse(ctx, o.Get(k).ToObject(rt)); err != nil {
return nil, fmt.Errorf("parsing HTTP credential options: %w", err)
}
b.HttpCredentials = credentials
case "ignoreHTTPSErrors":
b.IgnoreHTTPSErrors = o.Get(k).ToBoolean()
case "isMobile":
b.IsMobile = o.Get(k).ToBoolean()
case "javaScriptEnabled":
b.JavaScriptEnabled = o.Get(k).ToBoolean()
case "locale":
b.Locale = o.Get(k).String()
case "offline":
b.Offline = o.Get(k).ToBoolean()
case "permissions":
if ps, ok := o.Get(k).Export().([]any); ok {
for _, p := range ps {
b.Permissions = append(b.Permissions, fmt.Sprintf("%v", p))
}
}
case "reducedMotion":
switch common.ReducedMotion(o.Get(k).String()) { //nolint:exhaustive
case "reduce":
b.ReducedMotion = common.ReducedMotionReduce
default:
b.ReducedMotion = common.ReducedMotionNoPreference
}
case "screen":
var screen common.Screen
if err := screen.Parse(ctx, o.Get(k).ToObject(rt)); err != nil {
return nil, fmt.Errorf("parsing screen options: %w", err)
}
b.Screen = &screen
case "timezoneID":
b.TimezoneID = o.Get(k).String()
case "userAgent":
b.UserAgent = o.Get(k).String()
case "viewport":
var viewport common.Viewport
if err := viewport.Parse(ctx, o.Get(k).ToObject(rt)); err != nil {
return nil, fmt.Errorf("parsing viewport options: %w", err)
}
b.Viewport = &viewport
}
}

return b, nil
}
12 changes: 5 additions & 7 deletions browser/sync_browser_mapping.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ import (
"fmt"

"github.com/grafana/sobek"

"github.com/grafana/xk6-browser/common"
)

// syncMapBrowser is like mapBrowser but returns synchronous functions.
Expand Down Expand Up @@ -34,8 +32,8 @@ func syncMapBrowser(vu moduleVU) mapping { //nolint:funlen,cyclop
return b.IsConnected(), nil
},
"newContext": func(opts sobek.Value) (*sobek.Object, error) {
popts := common.NewBrowserContextOptions()
if err := popts.Parse(vu.Context(), opts); err != nil {
popts, err := parseBrowserContextOptions(vu.Context(), opts)
if err != nil {
return nil, fmt.Errorf("parsing browser.newContext options: %w", err)
}

Expand Down Expand Up @@ -71,9 +69,9 @@ func syncMapBrowser(vu moduleVU) mapping { //nolint:funlen,cyclop
return b.Version(), nil
},
"newPage": func(opts sobek.Value) (mapping, error) {
popts := common.NewBrowserContextOptions()
if err := popts.Parse(vu.Context(), opts); err != nil {
return nil, fmt.Errorf("parsing browser.newContext options: %w", err)
popts, err := parseBrowserContextOptions(vu.Context(), opts)
if err != nil {
return nil, fmt.Errorf("parsing browser.newPage options: %w", err)
}

b, err := vu.browser()
Expand Down
90 changes: 0 additions & 90 deletions common/browser_context_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,96 +98,6 @@ func NewBrowserContextOptions() *BrowserContextOptions {
}
}

// Parse parses the browser context options.
func (b *BrowserContextOptions) Parse(ctx context.Context, opts sobek.Value) error { //nolint:cyclop,funlen,gocognit
rt := k6ext.Runtime(ctx)
if !sobekValueExists(opts) {
return nil
}
o := opts.ToObject(rt)
for _, k := range o.Keys() {
switch k {
case "acceptDownloads":
b.AcceptDownloads = o.Get(k).ToBoolean()
case "downloadsPath":
b.DownloadsPath = o.Get(k).String()
case "bypassCSP":
b.BypassCSP = o.Get(k).ToBoolean()
case "colorScheme":
switch ColorScheme(o.Get(k).String()) { //nolint:exhaustive
case "light":
b.ColorScheme = ColorSchemeLight
case "dark":
b.ColorScheme = ColorSchemeDark
default:
b.ColorScheme = ColorSchemeNoPreference
}
case "deviceScaleFactor":
b.DeviceScaleFactor = o.Get(k).ToFloat()
case "extraHTTPHeaders":
headers := o.Get(k).ToObject(rt)
for _, k := range headers.Keys() {
b.ExtraHTTPHeaders[k] = headers.Get(k).String()
}
case "geolocation":
geolocation := NewGeolocation()
if err := geolocation.Parse(ctx, o.Get(k).ToObject(rt)); err != nil {
return err
}
b.Geolocation = geolocation
case "hasTouch":
b.HasTouch = o.Get(k).ToBoolean()
case "httpCredentials":
credentials := NewCredentials()
if err := credentials.Parse(ctx, o.Get(k).ToObject(rt)); err != nil {
return err
}
b.HttpCredentials = credentials
case "ignoreHTTPSErrors":
b.IgnoreHTTPSErrors = o.Get(k).ToBoolean()
case "isMobile":
b.IsMobile = o.Get(k).ToBoolean()
case "javaScriptEnabled":
b.JavaScriptEnabled = o.Get(k).ToBoolean()
case "locale":
b.Locale = o.Get(k).String()
case "offline":
b.Offline = o.Get(k).ToBoolean()
case "permissions":
if ps, ok := o.Get(k).Export().([]any); ok {
for _, p := range ps {
b.Permissions = append(b.Permissions, fmt.Sprintf("%v", p))
}
}
case "reducedMotion":
switch ReducedMotion(o.Get(k).String()) { //nolint:exhaustive
case "reduce":
b.ReducedMotion = ReducedMotionReduce
default:
b.ReducedMotion = ReducedMotionNoPreference
}
case "screen":
screen := &Screen{}
if err := screen.Parse(ctx, o.Get(k).ToObject(rt)); err != nil {
return err
}
b.Screen = screen
case "timezoneID":
b.TimezoneID = o.Get(k).String()
case "userAgent":
b.UserAgent = o.Get(k).String()
case "viewport":
viewport := &Viewport{}
if err := viewport.Parse(ctx, o.Get(k).ToObject(rt)); err != nil {
return err
}
b.Viewport = viewport
}
}

return nil
}

// WaitForEventOptions are the options used by the browserContext.waitForEvent API.
type WaitForEventOptions struct {
Timeout time.Duration
Expand Down
23 changes: 0 additions & 23 deletions common/browser_context_options_test.go

This file was deleted.

20 changes: 0 additions & 20 deletions common/browser_context_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -325,23 +325,3 @@ func TestFilterCookies(t *testing.T) {
})
}
}

func TestBrowserContextSetGeolocation(t *testing.T) {
vu := k6test.NewVU(t)

var opts BrowserContextOptions
err := opts.Parse(vu.Context(), vu.ToSobekValue((struct {
GeoLocation *Geolocation `js:"geolocation"`
}{
GeoLocation: &Geolocation{
Latitude: 1.0,
Longitude: 2.0,
Accuracy: 3.0,
},
})))
assert.NoError(t, err)
assert.NotNil(t, opts)
assert.Equal(t, 1.0, opts.Geolocation.Latitude)
assert.Equal(t, 2.0, opts.Geolocation.Longitude)
assert.Equal(t, 3.0, opts.Geolocation.Accuracy)
}

0 comments on commit 946e4cb

Please sign in to comment.