Skip to content

Commit

Permalink
Added ELEMENT_EXISTS function (#210)
Browse files Browse the repository at this point in the history
  • Loading branch information
ziflex authored Dec 19, 2018
1 parent 6b938f5 commit 7ca57c5
Show file tree
Hide file tree
Showing 12 changed files with 147 additions and 4 deletions.
26 changes: 23 additions & 3 deletions e2e/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ package main
import (
"flag"
"fmt"
"os"
"path/filepath"

"github.com/MontFerret/ferret/e2e/runner"
"github.com/MontFerret/ferret/e2e/server"
"github.com/rs/zerolog"
"os"
"path/filepath"
"regexp"
)

var (
Expand All @@ -29,6 +29,12 @@ var (
"http://0.0.0.0:9222",
"address of remote Chrome instance",
)

filter = flag.String(
"filter",
"",
"regexp expression to filter out tests",
)
)

func main() {
Expand All @@ -48,6 +54,19 @@ func main() {
Dir: filepath.Join(*pagesDir, "dynamic"),
})

var filterR *regexp.Regexp

if *filter != "" {
r, err := regexp.Compile(*filter)

if err != nil {
fmt.Println(err.Error())
os.Exit(1)
}

filterR = r
}

go func() {
if err := static.Start(); err != nil {
logger.Info().Timestamp().Msg("shutting down the static pages server")
Expand Down Expand Up @@ -79,6 +98,7 @@ func main() {
DynamicServerAddress: fmt.Sprintf("http://0.0.0.0:%d", dynamicPort),
CDPAddress: *cdp,
Dir: *testsDir,
Filter: filterR,
})

err := r.Run()
Expand Down
12 changes: 11 additions & 1 deletion e2e/runner/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"io/ioutil"
"os"
"path/filepath"
"regexp"
"time"
)

Expand All @@ -22,6 +23,7 @@ type (
DynamicServerAddress string
CDPAddress string
Dir string
Filter *regexp.Regexp
}

Result struct {
Expand Down Expand Up @@ -103,7 +105,15 @@ func (r *Runner) runQueries(dir string) ([]Result, error) {

// read scripts
for _, f := range files {
fName := filepath.Join(dir, f.Name())
n := f.Name()

if r.settings.Filter != nil {
if r.settings.Filter.Match([]byte(n)) != true {
continue
}
}

fName := filepath.Join(dir, n)
b, err := ioutil.ReadFile(fName)

if err != nil {
Expand Down
10 changes: 10 additions & 0 deletions e2e/tests/doc_element_exists.fql
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
LET url = @static + '/overview.html'
LET doc = PAGE(url)

LET expectedP = TRUE
LET actualP = ELEMENT_EXISTS(doc, '.section-nav')

LET expectedN = FALSE
LET actualN = ELEMENT_EXISTS(doc, '.foo-bar')

RETURN EXPECT(expectedP + expectedN, actualP + expectedN)
10 changes: 10 additions & 0 deletions e2e/tests/doc_element_exists_d.fql
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
LET url = @dynamic
LET doc = PAGE(url)

LET expectedP = TRUE
LET actualP = ELEMENT_EXISTS(doc, '.text-center')

LET expectedN = FALSE
LET actualN = ELEMENT_EXISTS(doc, '.foo-bar')

RETURN EXPECT(expectedP + expectedN, actualP + expectedN)
12 changes: 12 additions & 0 deletions e2e/tests/el_element_exists.fql
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
LET url = @static + '/value.html'
LET doc = PAGE(url)

LET el = ELEMENT(doc, "#listings_table")

LET expectedP = TRUE
LET actualP = ELEMENT_EXISTS(el, '.odd')

LET expectedN = FALSE
LET actualN = ELEMENT_EXISTS(el, '.foo-bar')

RETURN EXPECT(expectedP + expectedN, actualP + expectedN)
12 changes: 12 additions & 0 deletions e2e/tests/el_element_exists_d.fql
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
LET url = @dynamic
LET doc = PAGE(url)

LET el = ELEMENT(doc, "#root")

LET expectedP = TRUE
LET actualP = ELEMENT_EXISTS(el, '.jumbotron')

LET expectedN = FALSE
LET actualN = ELEMENT_EXISTS(el, '.foo-bar')

RETURN EXPECT(expectedP + expectedN, actualP + expectedN)
7 changes: 7 additions & 0 deletions pkg/drivers/cdp/document.go
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,13 @@ func (doc *HTMLDocument) CountBySelector(selector values.String) values.Int {
return doc.element.CountBySelector(selector)
}

func (doc *HTMLDocument) ExistsBySelector(selector values.String) values.Boolean {
doc.Lock()
defer doc.Unlock()

return doc.element.ExistsBySelector(selector)
}

func (doc *HTMLDocument) ClickBySelector(selector values.String) (values.Boolean, error) {
res, err := eval.Eval(
doc.client,
Expand Down
27 changes: 27 additions & 0 deletions pkg/drivers/cdp/element.go
Original file line number Diff line number Diff line change
Expand Up @@ -679,6 +679,33 @@ func (el *HTMLElement) CountBySelector(selector values.String) values.Int {
return values.NewInt(len(res.NodeIDs))
}

func (el *HTMLElement) ExistsBySelector(selector values.String) values.Boolean {
if !el.IsConnected() {
return values.False
}

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

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

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

return values.False
}

if res.NodeID == 0 {
return values.False
}

return values.True
}

func (el *HTMLElement) WaitForClass(class values.String, timeout values.Int) error {
task := events.NewWaitTask(
func() (core.Value, error) {
Expand Down
10 changes: 10 additions & 0 deletions pkg/drivers/http/element.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,16 @@ func (el *HTMLElement) CountBySelector(selector values.String) values.Int {
return values.NewInt(selection.Size())
}

func (el *HTMLElement) ExistsBySelector(selector values.String) values.Boolean {
selection := el.selection.Closest(selector.String())

if selection == nil {
return values.False
}

return values.True
}

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

Expand Down
2 changes: 2 additions & 0 deletions pkg/runtime/values/html.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ type (
InnerTextBySelectorAll(selector String) *Array

CountBySelector(selector String) Int

ExistsBySelector(selector String) Boolean
}

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

import (
"context"

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

// ElementExists returns a boolean value indicating whether there is an element matched by selector.
// @param docOrEl (HTMLDocument|HTMLElement) - Parent document or element.
// @param selector (String) - CSS selector.
// @returns (Boolean) - A boolean value indicating whether there is an element matched by selector.
func ElementExists(_ context.Context, args ...core.Value) (core.Value, error) {
el, selector, err := queryArgs(args)

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

return el.ExistsBySelector(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 @@ -21,6 +21,7 @@ func NewLib() map[string]core.Function {
"PAGE": Page,
"DOWNLOAD": Download,
"ELEMENT": Element,
"ELEMENT_EXISTS": ElementExists,
"ELEMENTS": Elements,
"ELEMENTS_COUNT": ElementsCount,
"HOVER": Hover,
Expand Down

0 comments on commit 7ca57c5

Please sign in to comment.