Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support of Element.nextElementSibling and Element.previousEleme… #569

Merged
merged 3 commits into from
Nov 14, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions e2e/pages/dynamic/components/pages/lists/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ const ITEMS = [{"artist":"Lil Tecca","track":"Ransom"},{"artist":"NLE Choppa","t

export default class ListsPage extends React.Component {
render() {
const items = ITEMS.map((i) => {
return e("li", { className: "list-group-item track"}, [
const items = ITEMS.map((i, idx) => {
return e("li", { className: "list-group-item track", 'data-index': idx }, [
e("div", { className: "track-details"}, [
e("h5", { className: "track-artist"}, i.artist),
e("small", { className: "track-name"}, i.track)
Expand Down
11 changes: 11 additions & 0 deletions e2e/pages/static/list.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>Ferret E2E SPA</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="./assets/bootstrap.min.css" crossorigin="anonymous">
</head>
<body class="text-center">
<div id="root"><div id="layout"><nav class="navbar navbar-expand-md navbar-dark bg-dark mb-4" id="navbar"><a class="navbar-brand active" aria-current="page" href="http://localhost:8080/#/">Ferret</a><button class="navbar-toggler" type="button"><span class="navbar-toggler-icon"></span></button><div class="collapse navbar-collapse"><ul class="navbar-nav mr-auto"><li class="nav-item"><a class="nav-link" href="http://localhost:8080/#/forms">Forms</a></li><li class="nav-item"><a class="nav-link" href="http://localhost:8080/#/navigation">Navigation</a></li><li class="nav-item"><a class="nav-link" href="http://localhost:8080/#/events">Events</a></li><li class="nav-item"><a class="nav-link" href="http://localhost:8080/#/iframe">iFrame</a></li></ul></div></nav><main class="container"><div id="tracks"><ul class="list-group track-list"><li class="list-group-item track" data-index="0"><div class="track-details"><h5 class="track-artist">Lil Tecca</h5><small class="track-name">Ransom</small></div></li><li class="list-group-item track" data-index="1"><div class="track-details"><h5 class="track-artist">NLE Choppa</h5><small class="track-name">Shotta Flow (Feat. Blueface) [Remix]</small></div></li><li class="list-group-item track" data-index="2"><div class="track-details"><h5 class="track-artist">Baby Jesus (DaBaby)</h5><small class="track-name">Suge</small></div></li><li class="list-group-item track" data-index="3"><div class="track-details"><h5 class="track-artist">NLE Choppa</h5><small class="track-name">Shotta Flow 3</small></div></li><li class="list-group-item track" data-index="4"><div class="track-details"><h5 class="track-artist">Lil Tecca </h5><small class="track-name">Lil Tecca - Did It Again</small></div></li><li class="list-group-item track" data-index="5"><div class="track-details"><h5 class="track-artist">NLE Choppa</h5><small class="track-name">Shotta Flow</small></div></li><li class="list-group-item track" data-index="6"><div class="track-details"><h5 class="track-artist">Ynw Melly</h5><small class="track-name">Dangerously In Love (772 Love Pt. 2)</small></div></li><li class="list-group-item track" data-index="7"><div class="track-details"><h5 class="track-artist">POLO G</h5><small class="track-name">Polo G feat. Lil TJay - Pop Out</small></div></li><li class="list-group-item track" data-index="8"><div class="track-details"><h5 class="track-artist">MUSTARD</h5><small class="track-name">Ballin' (feat. Roddy Ricch)</small></div></li><li class="list-group-item track" data-index="9"><div class="track-details"><h5 class="track-artist">Lil Nas X</h5><small class="track-name">Panini</small></div></li><li class="list-group-item track" data-index="10"><div class="track-details"><h5 class="track-artist">Juice WRLD</h5><small class="track-name">Juice Wrld - RUN</small></div></li><li class="list-group-item track" data-index="11"><div class="track-details"><h5 class="track-artist">Shordie Shordie</h5><small class="track-name">Betchua (Bitchuary)</small></div></li><li class="list-group-item track" data-index="12"><div class="track-details"><h5 class="track-artist">Post Malone</h5><small class="track-name">Goodbyes (feat. Young Thug)</small></div></li><li class="list-group-item track" data-index="13"><div class="track-details"><h5 class="track-artist">LIL UZI VERT</h5><small class="track-name">Sanguine Paradise</small></div></li><li class="list-group-item track" data-index="14"><div class="track-details"><h5 class="track-artist">Calboy</h5><small class="track-name">Envy Me</small></div></li><li class="list-group-item track" data-index="15"><div class="track-details"><h5 class="track-artist">Ambjaay</h5><small class="track-name">Uno</small></div></li><li class="list-group-item track" data-index="16"><div class="track-details"><h5 class="track-artist">Lil Tecca</h5><small class="track-name">Lil Tecca - Bossanova</small></div></li><li class="list-group-item track" data-index="17"><div class="track-details"><h5 class="track-artist">Lil Baby</h5><small class="track-name">Baby</small></div></li><li class="list-group-item track" data-index="18"><div class="track-details"><h5 class="track-artist">Lil Tjay</h5><small class="track-name">Lil Tjay - Brothers (Prod by JDONTHATRACK &amp; Protegebeatz)</small></div></li><li class="list-group-item track" data-index="19"><div class="track-details"><h5 class="track-artist">YK Osiris</h5><small class="track-name">Worth It</small></div></li></ul></div></main></div></div>
</body></html>
12 changes: 12 additions & 0 deletions e2e/tests/dynamic/element/siblings/next.fql
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
LET doc = DOCUMENT(@lab.cdn.dynamic + "/#/lists", { driver:"cdp" })

LET current = ELEMENT(doc, ".track")
T::NOT::NONE(current)
LET next = current.nextElementSibling
T::NOT::NONE(next)

LET currentIdx = TO_INT(current.attributes['data-index'])
LET nextIdx = TO_INT(next.attributes['data-index'])
T::GT(nextIdx, currentIdx)

RETURN NONE
12 changes: 12 additions & 0 deletions e2e/tests/dynamic/element/siblings/prev.fql
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
LET doc = DOCUMENT(@lab.cdn.dynamic + "/#/lists", { driver:"cdp" })

LET current = ELEMENT(doc, '[data-index="1"]')
T::NOT::NONE(current)
LET prev = current.previousElementSibling
T::NOT::NONE(prev)

LET currentIdx = TO_INT(current.attributes['data-index'])
LET prevIdx = TO_INT(prev.attributes['data-index'])
T::LT(prevIdx, currentIdx)

RETURN NONE
13 changes: 13 additions & 0 deletions e2e/tests/static/element/siblings/next.fql
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
LET url = @lab.cdn.static + '/list.html'
LET doc = DOCUMENT(url)

LET current = ELEMENT(doc, ".track")
T::NOT::NONE(current)
LET next = current.nextElementSibling.nextElementSibling
T::NOT::NONE(next)

LET currentIdx = TO_INT(current.attributes['data-index'])
LET nextIdx = TO_INT(next.attributes['data-index'])
T::GT(nextIdx, currentIdx)

RETURN NONE
13 changes: 13 additions & 0 deletions e2e/tests/static/element/siblings/prev.fql
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
LET url = @lab.cdn.static + '/list.html'
LET doc = DOCUMENT(url)

LET current = ELEMENT(doc, '[data-index="1"]')
T::NOT::NONE(current)
LET prev = current.previousElementSibling
T::NOT::NONE(prev)

LET currentIdx = TO_INT(current.attributes['data-index'])
LET prevIdx = TO_INT(prev.attributes['data-index'])
T::LT(prevIdx, currentIdx)

RETURN NONE
20 changes: 20 additions & 0 deletions pkg/compiler/compiler_member_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,26 @@ func TestMember(t *testing.T) {

So(string(out), ShouldEqual, `"Bob"`)
})

Convey("Computed property with quotes", func() {
c := compiler.New()

p := c.MustCompile(`
LET obj = {
attributes: {
'data-index': 1
}
}

RETURN obj.attributes['data-index']
`)

out, err := p.Run(context.Background())

So(err, ShouldBeNil)

So(string(out), ShouldEqual, "1")
})
})
}

Expand Down
45 changes: 45 additions & 0 deletions pkg/drivers/cdp/dom/element.go
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,51 @@ func (el *HTMLElement) GetChildNode(ctx context.Context, idx values.Int) (core.V
)
}

func (el *HTMLElement) GetPreviousElementSibling(ctx context.Context) (core.Value, error) {
return el.getSibling(ctx, templates.GetPreviousElementSibling())
}

func (el *HTMLElement) GetNextElementSibling(ctx context.Context) (core.Value, error) {
return el.getSibling(ctx, templates.GetNextElementSibling())
}

func (el *HTMLElement) getSibling(ctx context.Context, expr string) (core.Value, error) {
if el.IsDetached() {
return values.None, drivers.ErrDetached
}

obj, err := el.exec.EvalWithArgumentsAndReturnReference(ctx, expr, runtime.CallArgument{
ObjectID: &el.id.ObjectID,
})

if err != nil {
return values.None, err
}

if obj.Type != "object" || obj.ObjectID == nil {
return values.None, nil
}

repl, err := el.client.DOM.RequestNode(ctx, dom.NewRequestNodeArgs(*obj.ObjectID))

if err != nil {
return values.None, err
}

return LoadHTMLElementWithID(
ctx,
el.logger,
el.client,
el.dom,
el.input,
el.exec,
HTMLElementIdentity{
NodeID: repl.NodeID,
ObjectID: *obj.ObjectID,
},
)
}

func (el *HTMLElement) QuerySelector(ctx context.Context, selector values.String) (core.Value, error) {
if el.IsDetached() {
return values.None, drivers.ErrDetached
Expand Down
12 changes: 12 additions & 0 deletions pkg/drivers/cdp/templates/siblings.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package templates

const getPreviousElementSibling = "(el) => el.previousElementSibling"
const getNextElementSibling = "(el) => el.nextElementSibling"

func GetPreviousElementSibling() string {
return getPreviousElementSibling
}

func GetNextElementSibling() string {
return getNextElementSibling
}
4 changes: 4 additions & 0 deletions pkg/drivers/common/getter.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,10 @@ func GetInElement(ctx context.Context, el drivers.HTMLElement, path []core.Value
}

return values.GetIn(ctx, styles, path[1:])
case "previousElementSibling":
return el.GetPreviousElementSibling(ctx)
case "nextElementSibling":
return el.GetNextElementSibling(ctx)
default:
return GetInNode(ctx, el, path)
}
Expand Down
32 changes: 27 additions & 5 deletions pkg/drivers/http/element.go
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,26 @@ func (el *HTMLElement) Iterate(_ context.Context) (core.Iterator, error) {
return common.NewIterator(el)
}

func (el *HTMLElement) GetPreviousElementSibling(_ context.Context) (core.Value, error) {
sibling := el.selection.Prev()

if sibling == nil {
return values.None, nil
}

return NewHTMLElement(sibling)
}

func (el *HTMLElement) GetNextElementSibling(_ context.Context) (core.Value, error) {
sibling := el.selection.Next()

if sibling == nil {
return values.None, nil
}

return NewHTMLElement(sibling)
}

func (el *HTMLElement) Click(_ context.Context, _ values.Int) error {
return core.ErrNotSupported
}
Expand Down Expand Up @@ -608,12 +628,14 @@ func (el *HTMLElement) ensureAttrs() {
func (el *HTMLElement) parseAttrs() *values.Object {
obj := values.NewObject()

for _, name := range common.Attributes {
val, ok := el.selection.Attr(name)
if len(el.selection.Nodes) == 0 {
return obj
}

if ok {
obj.Set(values.NewString(name), values.NewString(val))
}
node := el.selection.Nodes[0]

for _, attr := range node.Attr {
obj.Set(values.NewString(attr.Key), values.NewString(attr.Val))
}

return obj
Expand Down
4 changes: 4 additions & 0 deletions pkg/drivers/value.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ type (

GetInnerTextBySelectorAll(ctx context.Context, selector values.String) (*values.Array, error)

GetPreviousElementSibling(ctx context.Context) (core.Value, error)

GetNextElementSibling(ctx context.Context) (core.Value, error)

Click(ctx context.Context, count values.Int) error

ClickBySelector(ctx context.Context, selector values.String, count values.Int) error
Expand Down