From b7df16cc887a0da2d29290888635d2c0a6a3defb Mon Sep 17 00:00:00 2001 From: oleiade Date: Thu, 12 May 2022 15:35:49 +0200 Subject: [PATCH] Make html.Selection.map return []goja.Value instead of []string --- js/modules/k6/html/html.go | 13 +++---- js/modules/k6/html/html_test.go | 64 ++++++++++++++++++++++++++++++--- 2 files changed, 66 insertions(+), 11 deletions(-) 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..f470a9470486 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,11 +442,48 @@ 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, []string{"select_multi"}, mapped) - } + assert.Equal(t, "select_multi", mapped[0].String()) + } + }) + t.Run("Valid XML", func(t *testing.T) { + rt := getTestRuntimeWithDoc(t, testXML) + testScript := ` + const buckets = 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 + }); + + if (buckets.length !== 1) { + throw new Error('Expected 2 buckets, got ' + buckets.length) + } + + if (buckets[0].name !== 'myBucketName') { + throw new Error('Expected bucket name to be "myBucketName", got ' + buckets[0].name) + } + + if (buckets[0].creationDate !== 'myCreationDateTimestamp') { + throw new Error('Expected bucket creation date to be "myCreationDateTimestamp", got ' + buckets[0].creationDate) + } + ` + + _, err := rt.RunString(testScript) + assert.NoError(t, err) }) }) t.Run("Next", func(t *testing.T) {