From 50d21c8eab589bb9d6f86cebf41b760222b85680 Mon Sep 17 00:00:00 2001 From: Jabar Asadi Date: Thu, 28 Dec 2023 23:15:44 +0100 Subject: [PATCH 1/2] feat: enabling the extraction of a specific selection from an element --- js/modules/k6/html/element.go | 12 +++++++++++ js/modules/k6/html/element_test.go | 9 +++++++++ js/modules/k6/html/html.go | 32 ++++++++++++++++++++++++++++++ js/modules/k6/html/html_test.go | 21 ++++++++++++++++++++ 4 files changed, 74 insertions(+) diff --git a/js/modules/k6/html/element.go b/js/modules/k6/html/element.go index ad80a701546..b8b655ff3a4 100644 --- a/js/modules/k6/html/element.go +++ b/js/modules/k6/html/element.go @@ -246,6 +246,18 @@ func (e Element) IsSameNode(v goja.Value) bool { return false } +// Selection returns a Selection object based on the current Element. +// +// This function is used to create a Selection object that represents the same HTML +// content as the Element. It is useful for performing operations or manipulations +// on the HTML content within the scope of this Element. +// +// Example: +// sel := element.Selection() +func (e Element) Selection() Selection { + return Selection{rt: e.sel.rt, sel: e.sel.sel, URL: e.sel.URL} +} + func (e Element) GetElementsByClassName(name string) []goja.Value { return elemList(Selection{e.sel.rt, e.sel.sel.Find("." + name), e.sel.URL}) } diff --git a/js/modules/k6/html/element_test.go b/js/modules/k6/html/element_test.go index 144f21eb8ef..f1f2fd03e31 100644 --- a/js/modules/k6/html/element_test.go +++ b/js/modules/k6/html/element_test.go @@ -228,6 +228,15 @@ func TestElement(t *testing.T) { assert.Contains(t, nodes[3].Export().(Element).TextContent(), "Maecenas augue ligula") } }) + t.Run("Selection", func(t *testing.T) { + t.Parallel() + rt := getTestRuntimeWithDoc(t, testHTMLElem) + + v, err := rt.RunString(`doc.find('div').get(0).selection().find('h2').text()`) + if assert.NoError(t, err) { + assert.Equal(t, "Nullam id nisi eget ex pharetra imperdiet.", v.String()) + } + }) t.Run("ClassList", func(t *testing.T) { t.Parallel() rt := getTestRuntimeWithDoc(t, testHTMLElem) diff --git a/js/modules/k6/html/html.go b/js/modules/k6/html/html.go index 180567a9c3a..ac2204aaa74 100644 --- a/js/modules/k6/html/html.go +++ b/js/modules/k6/html/html.go @@ -280,6 +280,38 @@ func (s Selection) Last() Selection { return Selection{s.rt, s.sel.Last(), s.URL} } +// FromElement creates a new Selection based on a specified Element. +// +// This function is useful for creating a new Selection object that +// encapsulates the same HTML structure as the provided Element. It +// is particularly helpful when you need to perform further operations +// or manipulations on the HTML content within the scope of this Element. +// If the provided value is not an Element, an empty Selection is returned. +// +// Example: +// sel := existingSelection.FromElement(jsElement) +func (s Selection) FromElement(v goja.Value) Selection { + elm, ok := v.Export().(Element) + if !ok { + // Return an empty Selection if the value is not an Element + return s.emptySelection() + } + + return Selection{rt: s.rt, sel: elm.sel.sel, URL: s.URL} +} + +// Locator selects HTML elements based on a CSS selector or XPath. +// +// This method is designed to provide a consistent way of selecting elements, +// similar to how 'page.locator' works in the 'k6-browser'. It uses goquery +// to perform the selection based on the given selector string. +// +// Example: +// sel := mySelection.Locator(".myClass") +func (s Selection) Locator(selector string) Selection { + return Selection{s.rt, s.sel.Find(selector), s.URL} +} + func (s Selection) Contents() Selection { return Selection{s.rt, s.sel.Contents(), s.URL} } diff --git a/js/modules/k6/html/html_test.go b/js/modules/k6/html/html_test.go index 19f3e912de9..19b4efd87d1 100644 --- a/js/modules/k6/html/html_test.go +++ b/js/modules/k6/html/html_test.go @@ -269,6 +269,27 @@ func TestParseHTML(t *testing.T) { assert.Equal(t, "form1", v.Export()) } }) + t.Run("FromElement", func(t *testing.T) { + t.Parallel() + rt := getTestRuntimeWithDoc(t, testHTML) + + _, err := rt.RunString(`var body = doc.find("body").get(0)`) + assert.NoError(t, err) + + v, err := rt.RunString(`doc.fromElement(body).find('#top').text()`) + if assert.NoError(t, err) { + assert.Equal(t, "Lorem ipsum", v.String()) + } + }) + t.Run("Locator", func(t *testing.T) { + t.Parallel() + rt := getTestRuntimeWithDoc(t, testHTML) + + v, err := rt.RunString(`doc.locator("#top").text()`) + if assert.NoError(t, err) { + assert.Equal(t, "Lorem ipsum", v.String()) + } + }) t.Run("Contents", func(t *testing.T) { t.Parallel() rt := getTestRuntimeWithDoc(t, testHTML) From 139495f040fa91bf38d1bcbc5462bf04632d79cc Mon Sep 17 00:00:00 2001 From: Jabar Asadi Date: Thu, 11 Jan 2024 15:11:08 +0100 Subject: [PATCH 2/2] chore: code review, remove FromElement and Locator functions from Selection class --- js/modules/k6/html/element.go | 2 +- js/modules/k6/html/html.go | 32 -------------------------------- js/modules/k6/html/html_test.go | 21 --------------------- 3 files changed, 1 insertion(+), 54 deletions(-) diff --git a/js/modules/k6/html/element.go b/js/modules/k6/html/element.go index b8b655ff3a4..022531b9a39 100644 --- a/js/modules/k6/html/element.go +++ b/js/modules/k6/html/element.go @@ -255,7 +255,7 @@ func (e Element) IsSameNode(v goja.Value) bool { // Example: // sel := element.Selection() func (e Element) Selection() Selection { - return Selection{rt: e.sel.rt, sel: e.sel.sel, URL: e.sel.URL} + return *e.sel } func (e Element) GetElementsByClassName(name string) []goja.Value { diff --git a/js/modules/k6/html/html.go b/js/modules/k6/html/html.go index ac2204aaa74..180567a9c3a 100644 --- a/js/modules/k6/html/html.go +++ b/js/modules/k6/html/html.go @@ -280,38 +280,6 @@ func (s Selection) Last() Selection { return Selection{s.rt, s.sel.Last(), s.URL} } -// FromElement creates a new Selection based on a specified Element. -// -// This function is useful for creating a new Selection object that -// encapsulates the same HTML structure as the provided Element. It -// is particularly helpful when you need to perform further operations -// or manipulations on the HTML content within the scope of this Element. -// If the provided value is not an Element, an empty Selection is returned. -// -// Example: -// sel := existingSelection.FromElement(jsElement) -func (s Selection) FromElement(v goja.Value) Selection { - elm, ok := v.Export().(Element) - if !ok { - // Return an empty Selection if the value is not an Element - return s.emptySelection() - } - - return Selection{rt: s.rt, sel: elm.sel.sel, URL: s.URL} -} - -// Locator selects HTML elements based on a CSS selector or XPath. -// -// This method is designed to provide a consistent way of selecting elements, -// similar to how 'page.locator' works in the 'k6-browser'. It uses goquery -// to perform the selection based on the given selector string. -// -// Example: -// sel := mySelection.Locator(".myClass") -func (s Selection) Locator(selector string) Selection { - return Selection{s.rt, s.sel.Find(selector), s.URL} -} - func (s Selection) Contents() Selection { return Selection{s.rt, s.sel.Contents(), s.URL} } diff --git a/js/modules/k6/html/html_test.go b/js/modules/k6/html/html_test.go index 19b4efd87d1..19f3e912de9 100644 --- a/js/modules/k6/html/html_test.go +++ b/js/modules/k6/html/html_test.go @@ -269,27 +269,6 @@ func TestParseHTML(t *testing.T) { assert.Equal(t, "form1", v.Export()) } }) - t.Run("FromElement", func(t *testing.T) { - t.Parallel() - rt := getTestRuntimeWithDoc(t, testHTML) - - _, err := rt.RunString(`var body = doc.find("body").get(0)`) - assert.NoError(t, err) - - v, err := rt.RunString(`doc.fromElement(body).find('#top').text()`) - if assert.NoError(t, err) { - assert.Equal(t, "Lorem ipsum", v.String()) - } - }) - t.Run("Locator", func(t *testing.T) { - t.Parallel() - rt := getTestRuntimeWithDoc(t, testHTML) - - v, err := rt.RunString(`doc.locator("#top").text()`) - if assert.NoError(t, err) { - assert.Equal(t, "Lorem ipsum", v.String()) - } - }) t.Run("Contents", func(t *testing.T) { t.Parallel() rt := getTestRuntimeWithDoc(t, testHTML)