diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5b73f543..21043acb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,7 @@
#### Fixed
- Scrolling position is not centered. [#343](https://github.com/MontFerret/ferret/pull/343)
- Unable to set custom logger fields. [#346](https://github.com/MontFerret/ferret/pull/346)
+- Fixed ``INNER_HTML``, ``INNER_TEXT``, ``INNER_HTML_SET``, ``INNER_TEXT_SET`` functions. [#347](https://github.com/MontFerret/ferret/pull/347)
- Unable to set custom headers. [#348](https://github.com/MontFerret/ferret/pull/348)
### 0.8.1
diff --git a/Makefile b/Makefile
index e43d1599..b5d46b2b 100644
--- a/Makefile
+++ b/Makefile
@@ -31,7 +31,7 @@ cover:
e2e:
go run ${DIR_E2E}/main.go --tests ${DIR_E2E}/tests --pages ${DIR_E2E}/pages
- # --filter=e2e/tests/**/xpath/*.fql
+ # --filter=e2e/tests/dynamic/element/inner_text/get_by_selector.fql
bench:
go test -run=XXX -bench=. ${DIR_PKG}/...
diff --git a/e2e/pages/dynamic/components/app.js b/e2e/pages/dynamic/components/app.js
index ff73d159..b703c2af 100644
--- a/e2e/pages/dynamic/components/app.js
+++ b/e2e/pages/dynamic/components/app.js
@@ -5,6 +5,7 @@ import EventsPage from './pages/events/index.js';
import IframePage from './pages/iframes/index.js';
import MediaPage from './pages/media/index.js';
import PaginationPage from './pages/pagination/index.js';
+import ListsPage from './pages/lists/index.js';
const e = React.createElement;
const Router = ReactRouter.Router;
@@ -61,6 +62,10 @@ export default React.memo(function AppComponent(params = {}) {
path: '/pagination',
component: PaginationPage
}),
+ e(Route, {
+ path: '/lists',
+ component: ListsPage
+ }),
]),
redirectTo
])
diff --git a/e2e/pages/dynamic/components/pages/lists/index.js b/e2e/pages/dynamic/components/pages/lists/index.js
new file mode 100644
index 00000000..9284eec9
--- /dev/null
+++ b/e2e/pages/dynamic/components/pages/lists/index.js
@@ -0,0 +1,20 @@
+const e = React.createElement;
+
+const ITEMS = [{"artist":"Lil Tecca","track":"Ransom"},{"artist":"NLE Choppa","track":"Shotta Flow (Feat. Blueface) [Remix]"},{"artist":"Baby Jesus (DaBaby)","track":"Suge"},{"artist":"NLE Choppa","track":"Shotta Flow 3"},{"artist":"Lil Tecca ","track":"Lil Tecca - Did It Again"},{"artist":"NLE Choppa","track":"Shotta Flow"},{"artist":"Ynw Melly","track":"Dangerously In Love (772 Love Pt. 2)"},{"artist":"POLO G","track":"Polo G feat. Lil TJay - Pop Out"},{"artist":"MUSTARD","track":"Ballin' (feat. Roddy Ricch)"},{"artist":"Lil Nas X","track":"Panini"},{"artist":"Juice WRLD","track":"Juice Wrld - RUN"},{"artist":"Shordie Shordie","track":"Betchua (Bitchuary)"},{"artist":"Post Malone","track":"Goodbyes (feat. Young Thug)"},{"artist":"LIL UZI VERT","track":"Sanguine Paradise"},{"artist":"Calboy","track":"Envy Me"},{"artist":"Ambjaay","track":"Uno"},{"artist":"Lil Tecca","track":"Lil Tecca - Bossanova"},{"artist":"Lil Baby","track":"Baby"},{"artist":"Lil Tjay","track":"Lil Tjay - Brothers (Prod by JDONTHATRACK & Protegebeatz)"},{"artist":"YK Osiris","track":"Worth It"}];
+
+export default class ListsPage extends React.Component {
+ render() {
+ const items = ITEMS.map((i) => {
+ return e("li", { className: "list-group-item track"}, [
+ e("div", { className: "track-details"}, [
+ e("h5", { className: "track-artist"}, i.artist),
+ e("small", { className: "track-name"}, i.track)
+ ])
+ ])
+ });
+
+ return e("div", { id: "tracks" }, [
+ e("ul", { className: "list-group track-list" }, items)
+ ])
+ }
+}
\ No newline at end of file
diff --git a/e2e/tests/dynamic/element/inner_html/get_by_selector.fql b/e2e/tests/dynamic/element/inner_html/get_by_selector.fql
index 3ee88477..f07dd48b 100644
--- a/e2e/tests/dynamic/element/inner_html/get_by_selector.fql
+++ b/e2e/tests/dynamic/element/inner_html/get_by_selector.fql
@@ -1,11 +1,34 @@
-LET url = @dynamic
+LET url = @dynamic + "/#/lists"
LET doc = DOCUMENT(url, true)
-LET el = ELEMENT(doc, ".jumbotron")
-LET expected = `Welcome to Ferret E2E test page!`
-LET actual = INNER_HTML(el, "h1")
+LET expected = [
+ {"details":'
Lil Tecca
Ransom'},
+ {"details":'NLE Choppa
Shotta Flow (Feat. Blueface) [Remix]'},
+ {"details":'Baby Jesus (DaBaby)
Suge'},
+ {"details":'NLE Choppa
Shotta Flow 3'},
+ {"details":'Lil Tecca
Lil Tecca - Did It Again'},
+ {"details":'NLE Choppa
Shotta Flow'},
+ {"details":'Ynw Melly
Dangerously In Love (772 Love Pt. 2)'},
+ {"details":'POLO G
Polo G feat. Lil TJay - Pop Out'},
+ {"details":`MUSTARD
Ballin' (feat. Roddy Ricch)`},
+ {"details":'Lil Nas X
Panini'},
+ {"details":'Juice WRLD
Juice Wrld - RUN'},
+ {"details":'Shordie Shordie
Betchua (Bitchuary)'},
+ {"details":'Post Malone
Goodbyes (feat. Young Thug)'},
+ {"details":'LIL UZI VERT
Sanguine Paradise'},
+ {"details":'Calboy
Envy Me'},
+ {"details":'Ambjaay
Uno'},
+ {"details":'Lil Tecca
Lil Tecca - Bossanova'},
+ {"details":'Lil Baby
Baby'},
+ {"details":'Lil Tjay
Lil Tjay - Brothers (Prod by JDONTHATRACK & Protegebeatz)'},
+ {"details":'YK Osiris
Worth It'}
+]
-LET r1 = '(\n|\s)'
-LET r2 = '(\n|\s)'
+LET actual = (
+ FOR item IN ELEMENTS(doc, '.track-list li')
+ RETURN {
+ details: INNER_HTML(item, '.track-details'),
+ }
+)
-RETURN EXPECT(REGEXP_REPLACE(expected, r1, ''), REGEXP_REPLACE(TRIM(actual), r2, ''))
\ No newline at end of file
+RETURN EXPECT(expected, actual)
\ No newline at end of file
diff --git a/e2e/tests/dynamic/element/inner_html/set_by_selector.fql b/e2e/tests/dynamic/element/inner_html/set_by_selector.fql
new file mode 100644
index 00000000..267ffcd8
--- /dev/null
+++ b/e2e/tests/dynamic/element/inner_html/set_by_selector.fql
@@ -0,0 +1,25 @@
+LET url = @dynamic + "/#/lists"
+LET doc = DOCUMENT(url, true)
+
+LET expected = [
+ {"details":'MEDUZA
Piece Of Your Heart (feat. Goodboys)'},
+ {"details":'Metanoia Music
Che Crozz x Orbis - Lift Me Up'}
+]
+
+LET html = (
+ FOR t IN expected
+ RETURN '' + t.details + '
'
+)
+
+INNER_HTML_SET(doc, '.track-list', CONCAT_SEPARATOR('\n', html))
+
+LET list = ELEMENT(doc, '.track-list')
+
+LET actual = (
+ FOR item IN ELEMENTS(doc, '.track-list li')
+ RETURN {
+ details: INNER_HTML(item, '.track-details'),
+ }
+)
+
+RETURN EXPECT(expected, actual)
\ No newline at end of file
diff --git a/e2e/tests/dynamic/element/inner_text/get_by_selector.fql b/e2e/tests/dynamic/element/inner_text/get_by_selector.fql
index 67125e87..1a8c65d3 100644
--- a/e2e/tests/dynamic/element/inner_text/get_by_selector.fql
+++ b/e2e/tests/dynamic/element/inner_text/get_by_selector.fql
@@ -1,11 +1,34 @@
-LET url = @dynamic
+LET url = @dynamic + "/#/lists"
LET doc = DOCUMENT(url, true)
-LET el = ELEMENT(doc, ".jumbotron")
-LET expected = `Welcome to Ferret E2E test page!`
-LET actual = INNER_TEXT(el, "h1")
+LET expected = [
+ {"artist":"Lil Tecca","track":"Ransom"},
+ {"artist":"NLE Choppa","track":"Shotta Flow (Feat. Blueface) [Remix]"},
+ {"artist":"Baby Jesus (DaBaby)","track":"Suge"},
+ {"artist":"NLE Choppa","track":"Shotta Flow 3"},
+ {"artist":"Lil Tecca","track":"Lil Tecca - Did It Again"},
+ {"artist":"NLE Choppa","track":"Shotta Flow"},
+ {"artist":"Ynw Melly","track":"Dangerously In Love (772 Love Pt. 2)"},
+ {"artist":"POLO G","track":"Polo G feat. Lil TJay - Pop Out"},
+ {"artist":"MUSTARD","track":"Ballin' (feat. Roddy Ricch)"},
+ {"artist":"Lil Nas X","track":"Panini"},
+ {"artist":"Juice WRLD","track":"Juice Wrld - RUN"},
+ {"artist":"Shordie Shordie","track":"Betchua (Bitchuary)"},
+ {"artist":"Post Malone","track":"Goodbyes (feat. Young Thug)"},
+ {"artist":"LIL UZI VERT","track":"Sanguine Paradise"},
+ {"artist":"Calboy","track":"Envy Me"},
+ {"artist":"Ambjaay","track":"Uno"},
+ {"artist":"Lil Tecca","track":"Lil Tecca - Bossanova"},
+ {"artist":"Lil Baby","track":"Baby"},
+ {"artist":"Lil Tjay","track":"Lil Tjay - Brothers (Prod by JDONTHATRACK & Protegebeatz)"},
+ {"artist":"YK Osiris","track":"Worth It"}
+]
+LET actual = (
+ FOR item IN ELEMENTS(doc, '.track-list li')
+ RETURN {
+ artist: TRIM(INNER_TEXT(item, '.track-artist')),
+ track: TRIM(INNER_TEXT(item, '.track-name'))
+ }
+)
-LET r1 = '(\n|\s)'
-LET r2 = '(\n|\s)'
-
-RETURN EXPECT(REGEXP_REPLACE(expected, r1, ''), REGEXP_REPLACE(TRIM(actual), r2, ''))
\ No newline at end of file
+RETURN EXPECT(expected, actual)
\ No newline at end of file
diff --git a/e2e/tests/dynamic/element/inner_text/set_by_selector.fql b/e2e/tests/dynamic/element/inner_text/set_by_selector.fql
new file mode 100644
index 00000000..d956a4f6
--- /dev/null
+++ b/e2e/tests/dynamic/element/inner_text/set_by_selector.fql
@@ -0,0 +1,37 @@
+LET url = @dynamic + "/#/lists"
+LET doc = DOCUMENT(url, true)
+
+LET expected = [
+ {
+ "artist":'MEDUZA',
+ "track": 'Piece Of Your Heart (feat. Goodboys)'
+ },
+ {
+ "artist": 'Metanoia Music',
+ "track": 'Che Crozz x Orbis - Lift Me Up'
+ }
+]
+
+LET f = (
+ FOR item, idx IN ELEMENTS(doc, '.track-list li')
+ LIMIT 2
+ LET value = expected[idx]
+
+ INNER_HTML_SET(item, '.track-artist', value.artist)
+ INNER_HTML_SET(item, '.track-name', value.track)
+
+ RETURN NONE
+)
+
+LET list = ELEMENT(doc, '.track-list')
+
+LET actual = (
+ FOR item IN ELEMENTS(doc, '.track-list li')
+ LIMIT 2
+ RETURN {
+ artist: TRIM(INNER_TEXT(item, '.track-artist')),
+ track: TRIM(INNER_TEXT(item, '.track-name'))
+ }
+)
+
+RETURN EXPECT(expected, actual)
\ No newline at end of file
diff --git a/examples/dynamic-page.fql b/examples/dynamic-page.fql
index c837ea96..cd25ac09 100644
--- a/examples/dynamic-page.fql
+++ b/examples/dynamic-page.fql
@@ -6,6 +6,6 @@ LET tracks = ELEMENTS(doc, '.chartTrack__details')
FOR track IN tracks
RETURN {
- artist: TRIM(INNER_TEXT(track, '.chartTrack__username')),
- track: TRIM(INNER_TEXT(track, '.chartTrack__title'))
+ artist: TRIM(INNER_TEXT(track, '.chartTrack__username')),
+ track: TRIM(INNER_TEXT(track, '.chartTrack__title'))
}
diff --git a/pkg/drivers/cdp/element.go b/pkg/drivers/cdp/element.go
index 680d3021..98c9aea5 100644
--- a/pkg/drivers/cdp/element.go
+++ b/pkg/drivers/cdp/element.go
@@ -727,7 +727,22 @@ func (el *HTMLElement) GetInnerTextBySelector(ctx context.Context, selector valu
return values.EmptyString, drivers.ErrDetached
}
- out, err := el.exec.EvalWithReturnValue(ctx, templates.GetInnerTextBySelector(selector.String()))
+ sel, err := selector.MarshalJSON()
+
+ if err != nil {
+ return values.EmptyString, err
+ }
+
+ out, err := el.exec.EvalWithArgumentsAndReturnValue(
+ ctx,
+ templates.GetInnerTextBySelector(),
+ runtime.CallArgument{
+ ObjectID: &el.id.objectID,
+ },
+ runtime.CallArgument{
+ Value: sel,
+ },
+ )
if err != nil {
return values.EmptyString, err
@@ -741,7 +756,31 @@ func (el *HTMLElement) SetInnerTextBySelector(ctx context.Context, selector, inn
return drivers.ErrDetached
}
- return el.exec.Eval(ctx, templates.SetInnerTextBySelector(selector.String(), innerText.String()))
+ sel, err := selector.MarshalJSON()
+
+ if err != nil {
+ return err
+ }
+
+ val, err := innerText.MarshalJSON()
+
+ if err != nil {
+ return err
+ }
+
+ return el.exec.EvalWithArguments(
+ ctx,
+ templates.SetInnerTextBySelector(),
+ runtime.CallArgument{
+ ObjectID: &el.id.objectID,
+ },
+ runtime.CallArgument{
+ Value: sel,
+ },
+ runtime.CallArgument{
+ Value: val,
+ },
+ )
}
func (el *HTMLElement) GetInnerTextBySelectorAll(ctx context.Context, selector values.String) (*values.Array, error) {
@@ -749,7 +788,22 @@ func (el *HTMLElement) GetInnerTextBySelectorAll(ctx context.Context, selector v
return values.NewArray(0), drivers.ErrDetached
}
- out, err := el.exec.EvalWithReturnValue(ctx, templates.GetInnerTextBySelectorAll(selector.String()))
+ sel, err := selector.MarshalJSON()
+
+ if err != nil {
+ return nil, err
+ }
+
+ out, err := el.exec.EvalWithArgumentsAndReturnValue(
+ ctx,
+ templates.GetInnerTextBySelectorAll(),
+ runtime.CallArgument{
+ ObjectID: &el.id.objectID,
+ },
+ runtime.CallArgument{
+ Value: sel,
+ },
+ )
if err != nil {
return values.NewArray(0), err
@@ -793,7 +847,22 @@ func (el *HTMLElement) GetInnerHTMLBySelector(ctx context.Context, selector valu
return values.EmptyString, drivers.ErrDetached
}
- out, err := el.exec.EvalWithReturnValue(ctx, templates.GetInnerHTMLBySelector(selector.String()))
+ sel, err := selector.MarshalJSON()
+
+ if err != nil {
+ return values.EmptyString, err
+ }
+
+ out, err := el.exec.EvalWithArgumentsAndReturnValue(
+ ctx,
+ templates.GetInnerHTMLBySelector(),
+ runtime.CallArgument{
+ ObjectID: &el.id.objectID,
+ },
+ runtime.CallArgument{
+ Value: sel,
+ },
+ )
if err != nil {
return values.EmptyString, err
@@ -807,7 +876,31 @@ func (el *HTMLElement) SetInnerHTMLBySelector(ctx context.Context, selector, inn
return drivers.ErrDetached
}
- return el.exec.Eval(ctx, templates.SetInnerHTMLBySelector(selector.String(), innerHTML.String()))
+ sel, err := selector.MarshalJSON()
+
+ if err != nil {
+ return err
+ }
+
+ val, err := innerHTML.MarshalJSON()
+
+ if err != nil {
+ return err
+ }
+
+ return el.exec.EvalWithArguments(
+ ctx,
+ templates.SetInnerHTMLBySelector(),
+ runtime.CallArgument{
+ ObjectID: &el.id.objectID,
+ },
+ runtime.CallArgument{
+ Value: sel,
+ },
+ runtime.CallArgument{
+ Value: val,
+ },
+ )
}
func (el *HTMLElement) GetInnerHTMLBySelectorAll(ctx context.Context, selector values.String) (*values.Array, error) {
@@ -815,7 +908,22 @@ func (el *HTMLElement) GetInnerHTMLBySelectorAll(ctx context.Context, selector v
return values.NewArray(0), drivers.ErrDetached
}
- out, err := el.exec.EvalWithReturnValue(ctx, templates.GetInnerHTMLBySelectorAll(selector.String()))
+ sel, err := selector.MarshalJSON()
+
+ if err != nil {
+ return values.NewArray(0), err
+ }
+
+ out, err := el.exec.EvalWithArgumentsAndReturnValue(
+ ctx,
+ templates.GetInnerHTMLBySelectorAll(),
+ runtime.CallArgument{
+ ObjectID: &el.id.objectID,
+ },
+ runtime.CallArgument{
+ Value: sel,
+ },
+ )
if err != nil {
return values.NewArray(0), err
diff --git a/pkg/drivers/cdp/templates/get_inner_html.go b/pkg/drivers/cdp/templates/get_inner_html.go
index 7a0d9e1d..93914229 100644
--- a/pkg/drivers/cdp/templates/get_inner_html.go
+++ b/pkg/drivers/cdp/templates/get_inner_html.go
@@ -5,28 +5,36 @@ import (
"github.com/MontFerret/ferret/pkg/drivers"
)
-func GetInnerHTMLBySelector(selector string) string {
- return fmt.Sprintf(`
- const selector = "%s";
- const found = document.querySelector(selector);
-
- if (found == null) {
- throw new Error('%s');
+var getInnerHTMLBySelectorTemplate = fmt.Sprintf(`
+ (el, selector) => {
+ const found = el.querySelector(selector);
+
+ if (found == null) {
+ throw new Error('%s');
+ }
+
+ return found.innerHTML;
}
+ `, drivers.ErrNotFound,
+)
- return found.innerHTML;
- `, selector, drivers.ErrNotFound)
+func GetInnerHTMLBySelector() string {
+ return getInnerHTMLBySelectorTemplate
}
-func GetInnerHTMLBySelectorAll(selector string) string {
- return fmt.Sprintf(`
- const selector = "%s";
- const found = document.querySelectorAll(selector);
-
- if (found == null) {
- throw new Error('%s');
+var getInnerHTMLBySelectorAllTemplate = fmt.Sprintf(`
+ (el, selector) => {
+ const found = el.querySelectorAll(selector);
+
+ if (found == null) {
+ throw new Error('%s');
+ }
+
+ return Array.from(found).map(i => i.innerHTML);
}
+ `, drivers.ErrNotFound,
+)
- return Array.from(found).map(i => i.innerHTML);
- `, selector, drivers.ErrNotFound)
+func GetInnerHTMLBySelectorAll() string {
+ return getInnerHTMLBySelectorAllTemplate
}
diff --git a/pkg/drivers/cdp/templates/get_inner_text.go b/pkg/drivers/cdp/templates/get_inner_text.go
index fe806c62..19b739ed 100644
--- a/pkg/drivers/cdp/templates/get_inner_text.go
+++ b/pkg/drivers/cdp/templates/get_inner_text.go
@@ -5,28 +5,36 @@ import (
"github.com/MontFerret/ferret/pkg/drivers"
)
-func GetInnerTextBySelector(selector string) string {
- return fmt.Sprintf(`
- const selector = "%s";
- const found = document.querySelector(selector);
+var getInnerTextBySelectorTemplate = fmt.Sprintf(`
+ (el, selector) => {
+ const found = el.querySelector(selector);
if (found == null) {
- throw new Error('%s');
+ throw new Error("%s");
}
return found.innerText;
- `, selector, drivers.ErrNotFound)
+ }
+ `, drivers.ErrNotFound,
+)
+
+func GetInnerTextBySelector() string {
+ return getInnerTextBySelectorTemplate
}
-func GetInnerTextBySelectorAll(selector string) string {
- return fmt.Sprintf(`
- const selector = "%s";
- const found = document.querySelectorAll(selector);
+var getInnerTextBySelectorAllTemplate = fmt.Sprintf(`
+ (el, selector) => {
+ const found = el.querySelectorAll(selector);
if (found == null) {
- throw new Error('%s');
+ throw new Error("%s");
}
return Array.from(found).map(i => i.innerText);
- `, selector, drivers.ErrNotFound)
+ }
+ `, drivers.ErrNotFound,
+)
+
+func GetInnerTextBySelectorAll() string {
+ return getInnerTextBySelectorAllTemplate
}
diff --git a/pkg/drivers/cdp/templates/set_inner_html.go b/pkg/drivers/cdp/templates/set_inner_html.go
index 6cdd5675..eb2b2995 100644
--- a/pkg/drivers/cdp/templates/set_inner_html.go
+++ b/pkg/drivers/cdp/templates/set_inner_html.go
@@ -15,19 +15,20 @@ func SetInnerHTML() string {
return setInnerHTMLTemplate
}
-func SetInnerHTMLBySelector(selector, innerHTML string) string {
- return fmt.Sprintf(`
- const selector = "%s";
- const found = document.querySelector(selector)
-
- if (found == null) {
- throw new Error('%s');
+var setInnerHTMLBySelectorTemplate = fmt.Sprintf(`
+ (el, selector, value) => {
+ const found = el.querySelector(selector);
+
+ if (found == null) {
+ throw new Error('%s');
+ }
+
+ found.innerHTML = value;
}
-
- found.innerHTML = "%s"
`,
- selector,
- drivers.ErrNotFound,
- innerHTML,
- )
+ drivers.ErrNotFound,
+)
+
+func SetInnerHTMLBySelector() string {
+ return setInnerHTMLBySelectorTemplate
}
diff --git a/pkg/drivers/cdp/templates/set_inner_text.go b/pkg/drivers/cdp/templates/set_inner_text.go
index 94a1a91b..5ba0023f 100644
--- a/pkg/drivers/cdp/templates/set_inner_text.go
+++ b/pkg/drivers/cdp/templates/set_inner_text.go
@@ -15,19 +15,20 @@ func SetInnerText() string {
return setInnerTextTemplate
}
-func SetInnerTextBySelector(selector, innerText string) string {
- return fmt.Sprintf(`
- const selector = "%s";
- const found = document.querySelector(selector)
-
- if (found == null) {
- throw new Error('%s');
+var setInnerTextBySelectorTemplate = fmt.Sprintf(`
+ (el, selector, value) => {
+ const found = el.querySelector(selector);
+
+ if (found == null) {
+ throw new Error('%s');
+ }
+
+ found.innerText = value;
}
-
- found.innerText = "%s"
`,
- selector,
- drivers.ErrNotFound,
- innerText,
- )
+ drivers.ErrNotFound,
+)
+
+func SetInnerTextBySelector() string {
+ return setInnerTextBySelectorTemplate
}