diff --git a/js/modules/k6/html/html.go b/js/modules/k6/html/html.go index 4720d3ec5e5d..1ad1b9deaf3a 100644 --- a/js/modules/k6/html/html.go +++ b/js/modules/k6/html/html.go @@ -426,21 +426,22 @@ func (s Selection) Is(v goja.Value) bool { } // Map implements ES5 Array.prototype.map -func (s Selection) Map(v goja.Value) []string { +func (s Selection) Map(v goja.Value) []goja.Value { gojaFn, isFn := goja.AssertFunction(v) if !isFn { common.Throw(s.rt, errors.New("the argument to map() must be a function")) } - fn := func(idx int, sel *goquery.Selection) string { + var values []goja.Value + s.sel.Each(func(idx int, sel *goquery.Selection) { selection := &Selection{sel: sel, URL: s.URL, rt: s.rt} + if fnRes, fnErr := gojaFn(v, s.rt.ToValue(idx), s.rt.ToValue(selection)); fnErr == nil { - return fnRes.String() + values = append(values, fnRes) } - return "" - } + }) - return s.sel.Map(fn) + return values } func (s Selection) Slice(start int, def ...int) Selection { diff --git a/js/modules/k6/html/html_test.go b/js/modules/k6/html/html_test.go index 6fec3cbe685d..24f01c145a21 100644 --- a/js/modules/k6/html/html_test.go +++ b/js/modules/k6/html/html_test.go @@ -66,6 +66,21 @@ const testHTML = ` ` +const testXML = ` + + + + myCreationDateTimestamp + myBucketName + + + + string + string + + +` + func getTestModuleInstance(t testing.TB) (*goja.Runtime, *ModuleInstance) { rt := goja.New() rt.SetFieldNameMapper(common.FieldNameMapper{}) @@ -409,10 +424,12 @@ func TestParseHTML(t *testing.T) { t.Run("Valid", func(t *testing.T) { v, err := rt.RunString(`doc.find("#select_multi option").map(function(idx, val) { return val.text() })`) if assert.NoError(t, err) { - mapped, ok := v.Export().([]string) + mapped, ok := v.Export().([]goja.Value) assert.True(t, ok) assert.Equal(t, 3, len(mapped)) - assert.Equal(t, []string{"option 1", "option 2", "option 3"}, mapped) + assert.Equal(t, "option 1", mapped[0].String()) + assert.Equal(t, "option 2", mapped[1].String()) + assert.Equal(t, "option 3", mapped[2].String()) } }) t.Run("Invalid arg", func(t *testing.T) { @@ -425,10 +442,41 @@ func TestParseHTML(t *testing.T) { t.Run("Map with attr must return string", func(t *testing.T) { v, err := rt.RunString(`doc.find("#select_multi").map(function(idx, val) { return val.attr("name") })`) if assert.NoError(t, err) { - mapped, ok := v.Export().([]string) + mapped, ok := v.Export().([]goja.Value) + assert.True(t, ok) + assert.Equal(t, 1, len(mapped)) + assert.Equal(t, "select_multi", mapped[0].String()) + } + }) + t.Run("Valid XML", func(t *testing.T) { + rt := getTestRuntimeWithDoc(t, testXML) + testScript := ` + doc + .find('Buckets') + .children() + .map(function (idx, bucket) { + let bucketObj = {} + bucket.children().each(function (idx, elem) { + switch (elem.nodeName()) { + case 'name': + Object.assign(bucketObj, { name: elem.textContent() }) + break + case 'creationdate': + Object.assign(bucketObj, { creationDate: elem.textContent() }) + break + } + }) + return bucketObj + }) + ` + + v, err := rt.RunString(testScript) + if assert.NoError(t, err) { + mapped, ok := v.Export().([]goja.Value) assert.True(t, ok) assert.Equal(t, 1, len(mapped)) - assert.Equal(t, []string{"select_multi"}, mapped) + assert.Equal(t, "myBucketName", mapped[0].ToObject(rt).Get("name").String()) + assert.Equal(t, "myCreationDateTimestamp", mapped[0].ToObject(rt).Get("creationDate").String()) } }) })