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

Commit c3f099a

Browse files
committed
Desobekify Browser
- Moves BrowserContextOptions out of the business logic. - Sets default options in NewBrowserContext to prevent nil pointer issues in the rest of the module. Later, we might think about turning some of these pointer fields into value types to take advantage of their zero values.
1 parent 6200369 commit c3f099a

9 files changed

+72
-62
lines changed

browser/browser_mapping.go

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010
)
1111

1212
// mapBrowser to the JS module.
13-
func mapBrowser(vu moduleVU) mapping { //nolint:funlen,cyclop
13+
func mapBrowser(vu moduleVU) mapping { //nolint:funlen,cyclop,gocognit
1414
return mapping{
1515
"context": func() (mapping, error) {
1616
b, err := vu.browser()
@@ -36,23 +36,24 @@ func mapBrowser(vu moduleVU) mapping { //nolint:funlen,cyclop
3636
return b.IsConnected(), nil
3737
},
3838
"newContext": func(opts sobek.Value) (*sobek.Promise, error) {
39+
popts := common.NewBrowserContextOptions()
40+
if err := popts.Parse(vu.Context(), opts); err != nil {
41+
return nil, fmt.Errorf("parsing browser.newContext options: %w", err)
42+
}
3943
return k6ext.Promise(vu.Context(), func() (any, error) {
4044
b, err := vu.browser()
4145
if err != nil {
4246
return nil, err
4347
}
44-
bctx, err := b.NewContext(opts)
48+
bctx, err := b.NewContext(popts)
4549
if err != nil {
4650
return nil, err //nolint:wrapcheck
4751
}
48-
4952
if err := initBrowserContext(bctx, vu.testRunID); err != nil {
5053
return nil, err
5154
}
5255

53-
m := mapBrowserContext(vu, bctx)
54-
55-
return m, nil
56+
return mapBrowserContext(vu, bctx), nil
5657
}), nil
5758
},
5859
"userAgent": func() (string, error) {
@@ -69,23 +70,26 @@ func mapBrowser(vu moduleVU) mapping { //nolint:funlen,cyclop
6970
}
7071
return b.Version(), nil
7172
},
72-
"newPage": func(opts sobek.Value) *sobek.Promise {
73+
"newPage": func(opts sobek.Value) (*sobek.Promise, error) {
74+
popts := common.NewBrowserContextOptions()
75+
if err := popts.Parse(vu.Context(), opts); err != nil {
76+
return nil, fmt.Errorf("parsing browser.newPage options: %w", err)
77+
}
7378
return k6ext.Promise(vu.Context(), func() (any, error) {
7479
b, err := vu.browser()
7580
if err != nil {
7681
return nil, err
7782
}
78-
page, err := b.NewPage(opts)
83+
page, err := b.NewPage(popts)
7984
if err != nil {
8085
return nil, err //nolint:wrapcheck
8186
}
82-
8387
if err := initBrowserContext(b.Context(), vu.testRunID); err != nil {
8488
return nil, err
8589
}
8690

8791
return mapPage(vu, page), nil
88-
})
92+
}), nil
8993
},
9094
}
9195
}

browser/mapping_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -264,8 +264,8 @@ type browserAPI interface {
264264
Context() *common.BrowserContext
265265
CloseContext()
266266
IsConnected() bool
267-
NewContext(opts sobek.Value) (*common.BrowserContext, error)
268-
NewPage(opts sobek.Value) (*common.Page, error)
267+
NewContext(opts *common.BrowserContextOptions) (*common.BrowserContext, error)
268+
NewPage(opts *common.BrowserContextOptions) (*common.Page, error)
269269
On(string) (bool, error)
270270
UserAgent() string
271271
Version() string

browser/sync_browser_mapping.go

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
package browser
22

33
import (
4+
"fmt"
5+
46
"github.com/grafana/sobek"
7+
8+
"github.com/grafana/xk6-browser/common"
59
)
610

711
// syncMapBrowser is like mapBrowser but returns synchronous functions.
@@ -30,11 +34,16 @@ func syncMapBrowser(vu moduleVU) mapping { //nolint:funlen,cyclop
3034
return b.IsConnected(), nil
3135
},
3236
"newContext": func(opts sobek.Value) (*sobek.Object, error) {
37+
popts := common.NewBrowserContextOptions()
38+
if err := popts.Parse(vu.Context(), opts); err != nil {
39+
return nil, fmt.Errorf("parsing browser.newContext options: %w", err)
40+
}
41+
3342
b, err := vu.browser()
3443
if err != nil {
3544
return nil, err
3645
}
37-
bctx, err := b.NewContext(opts)
46+
bctx, err := b.NewContext(popts)
3847
if err != nil {
3948
return nil, err //nolint:wrapcheck
4049
}
@@ -62,11 +71,16 @@ func syncMapBrowser(vu moduleVU) mapping { //nolint:funlen,cyclop
6271
return b.Version(), nil
6372
},
6473
"newPage": func(opts sobek.Value) (mapping, error) {
74+
popts := common.NewBrowserContextOptions()
75+
if err := popts.Parse(vu.Context(), opts); err != nil {
76+
return nil, fmt.Errorf("parsing browser.newContext options: %w", err)
77+
}
78+
6579
b, err := vu.browser()
6680
if err != nil {
6781
return nil, err
6882
}
69-
page, err := b.NewPage(opts)
83+
page, err := b.NewPage(popts)
7084
if err != nil {
7185
return nil, err //nolint:wrapcheck
7286
}

common/browser.go

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import (
1414
"github.com/chromedp/cdproto/cdp"
1515
"github.com/chromedp/cdproto/target"
1616
"github.com/gorilla/websocket"
17-
"github.com/grafana/sobek"
1817

1918
"github.com/grafana/xk6-browser/k6ext"
2019
"github.com/grafana/xk6-browser/log"
@@ -569,7 +568,7 @@ func (b *Browser) IsConnected() bool {
569568
}
570569

571570
// NewContext creates a new incognito-like browser context.
572-
func (b *Browser) NewContext(opts sobek.Value) (*BrowserContext, error) {
571+
func (b *Browser) NewContext(opts *BrowserContextOptions) (*BrowserContext, error) {
573572
_, span := TraceAPICall(b.ctx, "", "browser.newContext")
574573
defer span.End()
575574

@@ -588,14 +587,7 @@ func (b *Browser) NewContext(opts sobek.Value) (*BrowserContext, error) {
588587
return nil, err
589588
}
590589

591-
browserCtxOpts := NewBrowserContextOptions()
592-
if err := browserCtxOpts.Parse(b.ctx, opts); err != nil {
593-
err := fmt.Errorf("parsing newContext options: %w", err)
594-
spanRecordError(span, err)
595-
return nil, err
596-
}
597-
598-
browserCtx, err := NewBrowserContext(b.ctx, b, browserContextID, browserCtxOpts, b.logger)
590+
browserCtx, err := NewBrowserContext(b.ctx, b, browserContextID, opts, b.logger)
599591
if err != nil {
600592
err := fmt.Errorf("new context: %w", err)
601593
spanRecordError(span, err)
@@ -610,7 +602,7 @@ func (b *Browser) NewContext(opts sobek.Value) (*BrowserContext, error) {
610602
}
611603

612604
// NewPage creates a new tab in the browser window.
613-
func (b *Browser) NewPage(opts sobek.Value) (*Page, error) {
605+
func (b *Browser) NewPage(opts *BrowserContextOptions) (*Page, error) {
614606
_, span := TraceAPICall(b.ctx, "", "browser.newPage")
615607
defer span.End()
616608

common/browser_context.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,11 @@ type BrowserContext struct {
9090
func NewBrowserContext(
9191
ctx context.Context, browser *Browser, id cdp.BrowserContextID, opts *BrowserContextOptions, logger *log.Logger,
9292
) (*BrowserContext, error) {
93+
// set the default options if none provided.
94+
if opts == nil {
95+
opts = NewBrowserContextOptions()
96+
}
97+
9398
b := BrowserContext{
9499
BaseEventEmitter: NewBaseEventEmitter(ctx),
95100
ctx: ctx,
@@ -101,7 +106,7 @@ func NewBrowserContext(
101106
timeoutSettings: NewTimeoutSettings(nil),
102107
}
103108

104-
if opts != nil && len(opts.Permissions) > 0 {
109+
if len(opts.Permissions) > 0 {
105110
err := b.GrantPermissions(opts.Permissions, NewGrantPermissionsOptions())
106111
if err != nil {
107112
return nil, err

tests/browser_context_options_test.go

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,12 @@ func TestBrowserContextOptionsSetViewport(t *testing.T) {
5151
t.Parallel()
5252

5353
tb := newTestBrowser(t)
54-
bctx, err := tb.NewContext(tb.toSobekValue(struct {
55-
Viewport common.Viewport `js:"viewport"`
56-
}{
57-
Viewport: common.Viewport{
58-
Width: 800,
59-
Height: 600,
60-
},
61-
}))
54+
opts := common.NewBrowserContextOptions()
55+
opts.Viewport = &common.Viewport{
56+
Width: 800,
57+
Height: 600,
58+
}
59+
bctx, err := tb.NewContext(opts)
6260
require.NoError(t, err)
6361
t.Cleanup(func() {
6462
if err := bctx.Close(); err != nil {
@@ -77,19 +75,19 @@ func TestBrowserContextOptionsExtraHTTPHeaders(t *testing.T) {
7775
t.Parallel()
7876

7977
tb := newTestBrowser(t, withHTTPServer())
80-
bctx, err := tb.NewContext(tb.toSobekValue(struct {
81-
ExtraHTTPHeaders map[string]string `js:"extraHTTPHeaders"`
82-
}{
83-
ExtraHTTPHeaders: map[string]string{
84-
"Some-Header": "Some-Value",
85-
},
86-
}))
78+
79+
opts := common.NewBrowserContextOptions()
80+
opts.ExtraHTTPHeaders = map[string]string{
81+
"Some-Header": "Some-Value",
82+
}
83+
bctx, err := tb.NewContext(opts)
8784
require.NoError(t, err)
8885
t.Cleanup(func() {
8986
if err := bctx.Close(); err != nil {
9087
t.Log("closing browser context:", err)
9188
}
9289
})
90+
9391
p, err := bctx.NewPage()
9492
require.NoError(t, err)
9593

tests/element_handle_test.go

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -181,17 +181,15 @@ func TestElementHandleClickConcealedLink(t *testing.T) {
181181
)
182182

183183
tb := newTestBrowser(t, withFileServer())
184-
bc, err := tb.NewContext(
185-
tb.toSobekValue(struct {
186-
Viewport common.Viewport `js:"viewport"`
187-
}{
188-
Viewport: common.Viewport{
189-
Width: 500,
190-
Height: 240,
191-
},
192-
}),
193-
)
184+
185+
bcopts := common.NewBrowserContextOptions()
186+
bcopts.Viewport = &common.Viewport{
187+
Width: 500,
188+
Height: 240,
189+
}
190+
bc, err := tb.NewContext(bcopts)
194191
require.NoError(t, err)
192+
195193
p, err := bc.NewPage()
196194
require.NoError(t, err)
197195

tests/network_manager_test.go

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -112,21 +112,20 @@ func TestBasicAuth(t *testing.T) {
112112
tb.Helper()
113113

114114
browser := newTestBrowser(t, withHTTPServer())
115-
bc, err := browser.NewContext(
116-
browser.toSobekValue(struct {
117-
HttpCredentials *common.Credentials `js:"httpCredentials"` //nolint:revive
118-
}{
119-
HttpCredentials: &common.Credentials{
120-
Username: user,
121-
Password: pass,
122-
},
123-
}))
115+
116+
bcopts := common.NewBrowserContextOptions()
117+
bcopts.HttpCredentials = &common.Credentials{
118+
Username: validUser,
119+
Password: validPassword,
120+
}
121+
bc, err := browser.NewContext(bcopts)
124122
require.NoError(t, err)
123+
125124
p, err := bc.NewPage()
126125
require.NoError(t, err)
127126

128127
url := browser.url(
129-
fmt.Sprintf("/basic-auth/%s/%s", validUser, validPassword),
128+
fmt.Sprintf("/basic-auth/%s/%s", user, pass),
130129
)
131130
opts := &common.FrameGotoOptions{
132131
WaitUntil: common.LifecycleEventLoad,

tests/test_browser.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ func withSkipClose() func(*testBrowser) {
253253

254254
// NewPage is a wrapper around Browser.NewPage that fails the test if an
255255
// error occurs. Added this helper to avoid boilerplate code in tests.
256-
func (b *testBrowser) NewPage(opts sobek.Value) *common.Page {
256+
func (b *testBrowser) NewPage(opts *common.BrowserContextOptions) *common.Page {
257257
b.t.Helper()
258258

259259
p, err := b.Browser.NewPage(opts)

0 commit comments

Comments
 (0)