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

Commit 6f95756

Browse files
committed
Add wildcard mappings and tests
1 parent 4e157b0 commit 6f95756

File tree

2 files changed

+149
-0
lines changed

2 files changed

+149
-0
lines changed

browser/mapping.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,18 @@ import (
1717
// and customization over our API.
1818
type mapping map[string]any
1919

20+
// wildcards is a list of extra mappings for our API (api/).
21+
func wildcards() map[string]string {
22+
return map[string]string{
23+
"Page.query": "$",
24+
"Page.queryAll": "$$",
25+
"Frame.query": "$",
26+
"Frame.queryAll": "$$",
27+
"ElementHandle.query": "$",
28+
"ElementHandle.queryAll": "$$",
29+
}
30+
}
31+
2032
// mapBrowserToGoja maps the browser API to the JS module.
2133
// The motivation of this mapping was to support $ and $$ wildcard
2234
// methods.

browser/mapping_test.go

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
package browser
2+
3+
import (
4+
"reflect"
5+
"strings"
6+
"testing"
7+
8+
"github.com/dop251/goja"
9+
"github.com/stretchr/testify/require"
10+
11+
"github.com/grafana/xk6-browser/api"
12+
"github.com/grafana/xk6-browser/chromium"
13+
"github.com/grafana/xk6-browser/common"
14+
15+
k6common "go.k6.io/k6/js/common"
16+
k6modulestest "go.k6.io/k6/js/modulestest"
17+
k6metrics "go.k6.io/k6/metrics"
18+
)
19+
20+
// TestMappings tests that all the methods of the API (api/) are
21+
// to the module. This is to ensure that we don't forget to map
22+
// a new method to the module.
23+
func TestMappings(t *testing.T) {
24+
t.Parallel()
25+
26+
vu := &k6modulestest.VU{
27+
RuntimeField: goja.New(),
28+
InitEnvField: &k6common.InitEnvironment{
29+
Registry: k6metrics.NewRegistry(),
30+
},
31+
}
32+
rt := vu.Runtime()
33+
34+
type test struct {
35+
apiObj any
36+
mapp func() mapping
37+
}
38+
mappers := map[string]test{
39+
"browserType": {
40+
apiObj: (*api.BrowserType)(nil),
41+
mapp: func() mapping {
42+
return mapBrowserType(rt, &chromium.BrowserType{})
43+
},
44+
},
45+
"browser": {
46+
apiObj: (*api.Browser)(nil),
47+
mapp: func() mapping {
48+
return mapBrowser(rt, &chromium.Browser{})
49+
},
50+
},
51+
"browserContext": {
52+
apiObj: (*api.BrowserContext)(nil),
53+
mapp: func() mapping {
54+
return mapBrowserContext(rt, &common.BrowserContext{})
55+
},
56+
},
57+
"page": {
58+
apiObj: (*api.Page)(nil),
59+
mapp: func() mapping {
60+
return mapPage(rt, &common.Page{})
61+
},
62+
},
63+
"elementHandle": {
64+
apiObj: (*api.ElementHandle)(nil),
65+
mapp: func() mapping {
66+
return mapElementHandle(rt, &common.ElementHandle{})
67+
},
68+
},
69+
"frame": {
70+
apiObj: (*api.Frame)(nil),
71+
mapp: func() mapping {
72+
return mapFrame(rt, &common.Frame{})
73+
},
74+
},
75+
"mapRequest": {
76+
apiObj: (*api.Request)(nil),
77+
mapp: func() mapping {
78+
return mapRequest(rt, &common.Request{})
79+
},
80+
},
81+
"mapResponse": {
82+
apiObj: (*api.Response)(nil),
83+
mapp: func() mapping {
84+
return mapResponse(rt, &common.Response{})
85+
},
86+
},
87+
}
88+
89+
wildcards := wildcards()
90+
91+
for name, tt := range mappers {
92+
tt := tt
93+
t.Run(name, func(t *testing.T) {
94+
t.Parallel()
95+
96+
var (
97+
typ = reflect.TypeOf(tt.apiObj).Elem()
98+
mapped = tt.mapp()
99+
)
100+
for i := 0; i < typ.NumMethod(); i++ {
101+
method := typ.Method(i)
102+
require.NotNil(t, method)
103+
104+
m := toFirstLetterLower(method.Name)
105+
// change the method name if it is mapped to a wildcard
106+
// method. these wildcard methods are not exist on our
107+
// API. so we need to use the mapped method instead.
108+
if wm, ok := isWildcard(wildcards, typ.Name(), m); ok {
109+
m = wm
110+
}
111+
if _, ok := mapped[m]; !ok {
112+
t.Errorf("method %s not found", m)
113+
}
114+
}
115+
})
116+
}
117+
}
118+
119+
// toFirstLetterLower converts the first letter of the string to lower case.
120+
func toFirstLetterLower(s string) string {
121+
// Special case for URL.
122+
// Instead of loading up an acronyms list, just do this.
123+
// Good enough for our purposes.
124+
if s == "URL" {
125+
return "url"
126+
}
127+
return strings.ToLower(s[:1]) + s[1:]
128+
}
129+
130+
// isWildcard returns true if the method is a wildcard method and
131+
// returns the name of the method to be called instead of the original
132+
// method.
133+
func isWildcard(wildcards map[string]string, typ, method string) (string, bool) {
134+
name := typ + "." + method
135+
s, ok := wildcards[name]
136+
return s, ok
137+
}

0 commit comments

Comments
 (0)