Skip to content

Commit

Permalink
Feature/#105 elements count (#109)
Browse files Browse the repository at this point in the history
* #105 Added ELEMENTS_COUNT function

* Some minor updates

* Invalid return type
  • Loading branch information
ziflex authored Oct 13, 2018
1 parent 495cc34 commit 42757a2
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 3 deletions.
12 changes: 12 additions & 0 deletions pkg/html/dynamic/document.go
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,13 @@ func (doc *HTMLDocument) InnerTextBySelectorAll(selector values.String) *values.
return doc.element.InnerTextBySelectorAll(selector)
}

func (doc *HTMLDocument) CountBySelector(selector values.String) values.Int {
doc.Lock()
defer doc.Unlock()

return doc.element.CountBySelector(selector)
}

func (doc *HTMLDocument) ClickBySelector(selector values.String) (values.Boolean, error) {
res, err := eval.Eval(
doc.client,
Expand Down Expand Up @@ -567,6 +574,11 @@ func (doc *HTMLDocument) WaitForClassAll(selector, class values.String, timeout
}

func (doc *HTMLDocument) WaitForNavigation(timeout values.Int) error {
// do not wait
if timeout == 0 {
return nil
}

onEvent := make(chan struct{})
listener := func(_ interface{}) {
close(onEvent)
Expand Down
23 changes: 23 additions & 0 deletions pkg/html/dynamic/element.go
Original file line number Diff line number Diff line change
Expand Up @@ -681,6 +681,29 @@ func (el *HTMLElement) InnerHTMLBySelectorAll(selector values.String) *values.Ar
return arr
}

func (el *HTMLElement) CountBySelector(selector values.String) values.Int {
if !el.IsConnected() {
return values.ZeroInt
}

ctx, cancel := contextWithTimeout()
defer cancel()

// TODO: Can we use RemoteObjectID or BackendID instead of NodeId?
selectorArgs := dom.NewQuerySelectorAllArgs(el.id.nodeID, selector.String())
res, err := el.client.DOM.QuerySelectorAll(ctx, selectorArgs)

if err != nil {
el.logError(err).
Str("selector", selector.String()).
Msg("failed to retrieve nodes by selector")

return values.ZeroInt
}

return values.NewInt(len(res.NodeIDs))
}

func (el *HTMLElement) Click() (values.Boolean, error) {
ctx, cancel := contextWithTimeout()

Expand Down
10 changes: 10 additions & 0 deletions pkg/html/static/element.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,16 @@ func (el *HTMLElement) InnerTextBySelectorAll(selector values.String) *values.Ar
return arr
}

func (el *HTMLElement) CountBySelector(selector values.String) values.Int {
selection := el.selection.Find(selector.String())

if selection == nil {
return values.ZeroInt
}

return values.NewInt(selection.Size())
}

func (el *HTMLElement) parseAttrs() *values.Object {
obj := values.NewObject()

Expand Down
27 changes: 24 additions & 3 deletions pkg/html/static/element_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package static_test
import (
"bytes"
"github.com/MontFerret/ferret/pkg/html/static"
"github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/PuerkitoBio/goquery"
. "github.com/smartystreets/goconvey/convey"
"testing"
Expand Down Expand Up @@ -297,7 +298,7 @@ func TestElement(t *testing.T) {
So(el.Length(), ShouldEqual, 4)
})

Convey(".Read", t, func() {
Convey(".Value", t, func() {
buff := bytes.NewBuffer([]byte(`
<html>
<head></head>
Expand Down Expand Up @@ -385,14 +386,34 @@ func TestElement(t *testing.T) {

So(err, ShouldBeNil)

el, err := static.NewHTMLElement(doc.Find("body .card-img-top:nth-child(1)"))
el, err := static.NewHTMLElement(doc.Selection)

So(err, ShouldBeNil)

v := el.NodeName()
found := el.QuerySelector(values.NewString("body .card-img-top:nth-child(1)"))

So(found, ShouldNotEqual, values.None)

v := found.(values.HTMLNode).NodeName()

So(err, ShouldBeNil)

So(v, ShouldEqual, "img")
})

Convey(".CountBySelector", t, func() {
buff := bytes.NewBuffer([]byte(doc))

doc, err := goquery.NewDocumentFromReader(buff)

So(err, ShouldBeNil)

el, err := static.NewHTMLElement(doc.Selection)

So(err, ShouldBeNil)

v := el.CountBySelector(values.NewString("head meta"))

So(v, ShouldEqual, 4)
})
}
2 changes: 2 additions & 0 deletions pkg/runtime/values/html.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ type (
InnerTextBySelector(selector String) String

InnerTextBySelectorAll(selector String) *Array

CountBySelector(selector String) Int
}

HTMLDocument interface {
Expand Down
24 changes: 24 additions & 0 deletions pkg/stdlib/html/elements_count.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package html

import (
"context"
"github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values"
)

/*
* Returns a number of found HTML elements by a given CSS selector.
* Returns an empty array if element not found.
* @param docOrEl (HTMLDocument|HTMLElement) - Parent document or element.
* @param selector (String) - CSS selector.
* @returns (Int) - A number of found HTML elements by a given CSS selector.
*/
func ElementsCount(_ context.Context, args ...core.Value) (core.Value, error) {
el, selector, err := queryArgs(args)

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

return el.CountBySelector(selector), nil
}
1 change: 1 addition & 0 deletions pkg/stdlib/html/lib.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ func NewLib() map[string]core.Function {
"DOCUMENT_PARSE": DocumentParse,
"ELEMENT": Element,
"ELEMENTS": Elements,
"ELEMENTS_COUNT": ElementsCount,
"WAIT_ELEMENT": WaitElement,
"WAIT_NAVIGATION": WaitNavigation,
"WAIT_CLASS": WaitClass,
Expand Down

0 comments on commit 42757a2

Please sign in to comment.