Skip to content

Commit

Permalink
abstract eval with EvalOptions
Browse files Browse the repository at this point in the history
  • Loading branch information
ysmood committed Aug 20, 2020
1 parent 2a7d836 commit 79db58d
Show file tree
Hide file tree
Showing 14 changed files with 176 additions and 147 deletions.
23 changes: 9 additions & 14 deletions dev_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"time"

"github.com/go-rod/rod/lib/assets"
"github.com/go-rod/rod/lib/assets/js"
"github.com/go-rod/rod/lib/launcher"
"github.com/go-rod/rod/lib/proto"
"github.com/go-rod/rod/lib/utils"
Expand Down Expand Up @@ -84,22 +85,20 @@ func (p *Page) Overlay(left, top, width, height float64, msg string) (remove fun
root := p.Root()
id := kit.RandString(8)

js, jsArgs := jsHelper("overlay", Array{
_, err := root.EvalWithOptions(jsHelper(js.Overlay, Array{
id,
left,
top,
width,
height,
msg,
})
_, err := root.Eval(true, "", js, jsArgs)
}))
if err != nil {
p.browser.traceLogErr(err)
}

remove = func() {
js, jsArgs := jsHelper("removeOverlay", Array{id})
_, _ = root.Eval(true, "", js, jsArgs)
_, _ = root.EvalWithOptions(jsHelper(js.RemoveOverlay, Array{id}))
}

return
Expand All @@ -116,18 +115,16 @@ func (p *Page) ExposeJSHelper() *Page {
func (el *Element) Trace(msg string) (removeOverlay func()) {
id := kit.RandString(8)

js, jsArgs := jsHelper("elementOverlay", Array{
_, err := el.EvalWithOptions(jsHelper(js.ElementOverlay, Array{
id,
msg,
})
_, err := el.Eval(true, js, jsArgs)
}))
if err != nil {
el.page.browser.traceLogErr(err)
}

removeOverlay = func() {
js, jsArgs := jsHelper("removeOverlay", Array{id})
_, _ = el.Eval(true, js, jsArgs)
_, _ = el.EvalWithOptions(jsHelper(js.RemoveOverlay, Array{id}))
}

return
Expand Down Expand Up @@ -196,13 +193,11 @@ func defaultTraceLogErr(err error) {
}

func (m *Mouse) initMouseTracer() {
js, params := jsHelper("initMouseTracer", Array{m.id, assets.MousePointer})
_, _ = m.page.Eval(true, "", js, params)
_, _ = m.page.EvalWithOptions(jsHelper(js.InitMouseTracer, Array{m.id, assets.MousePointer}))
}

func (m *Mouse) updateMouseTracer() bool {
js, jsArgs := jsHelper("updateMouseTracer", Array{m.id, m.x, m.y})
res, err := m.page.Eval(true, "", js, jsArgs)
res, err := m.page.EvalWithOptions(jsHelper(js.UpdateMouseTracer, Array{m.id, m.x, m.y}))
if err != nil {
return true
}
Expand Down
69 changes: 32 additions & 37 deletions element.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

"github.com/tidwall/gjson"

"github.com/go-rod/rod/lib/assets/js"
"github.com/go-rod/rod/lib/proto"
"github.com/go-rod/rod/lib/utils"
"github.com/ysmood/kit"
Expand All @@ -35,7 +36,7 @@ func (el *Element) Focus() error {
return err
}

_, err = el.Eval(true, `this.focus()`, nil)
_, err = el.Eval(`this.focus()`)
return err
}

Expand Down Expand Up @@ -103,7 +104,7 @@ func (el *Element) Clickable() (bool, error) {
return false, err
}

scroll, err := el.page.Root().Eval(true, "", `{ x: window.scrollX, y: window.scrollY }`, nil)
scroll, err := el.page.Root().Eval(`{ x: window.scrollX, y: window.scrollY }`)
if err != nil {
return false, err
}
Expand Down Expand Up @@ -164,8 +165,7 @@ func (el *Element) SelectText(regex string) error {
defer el.tryTrace("select text: " + regex)()
el.page.browser.trySlowmotion()

js, jsArgs := jsHelper("selectText", Array{regex})
_, err = el.Eval(true, js, jsArgs)
_, err = el.EvalWithOptions(jsHelper(js.SelectText, Array{regex}))
return err
}

Expand All @@ -179,8 +179,7 @@ func (el *Element) SelectAllText() error {
defer el.tryTrace("select all text")()
el.page.browser.trySlowmotion()

js, jsArgs := jsHelper("selectAllText", nil)
_, err = el.Eval(true, js, jsArgs)
_, err = el.EvalWithOptions(jsHelper(js.SelectAllText, nil))
return err
}

Expand All @@ -203,14 +202,13 @@ func (el *Element) Input(text string) error {
return err
}

js, jsArgs := jsHelper("inputEvent", nil)
_, err = el.Eval(true, js, jsArgs)
_, err = el.EvalWithOptions(jsHelper(js.InputEvent, nil))
return err
}

// Blur is similar to the method Blur
func (el *Element) Blur() error {
_, err := el.Eval(true, "this.blur()", nil)
_, err := el.Eval("this.blur()")
return err
}

Expand All @@ -226,14 +224,13 @@ func (el *Element) Select(selectors []string) error {
strings.Join(selectors, "; ")))()
el.page.browser.trySlowmotion()

js, jsArgs := jsHelper("select", Array{selectors})
_, err = el.Eval(true, js, jsArgs)
_, err = el.EvalWithOptions(jsHelper(js.Select, Array{selectors}))
return err
}

// Matches checks if the element can be selected by the css selector
func (el *Element) Matches(selector string) (bool, error) {
res, err := el.Eval(true, `s => this.matches(s)`, Array{selector})
res, err := el.Eval(`s => this.matches(s)`, selector)
if err != nil {
return false, err
}
Expand All @@ -242,7 +239,7 @@ func (el *Element) Matches(selector string) (bool, error) {

// Attribute is similar to the method Attribute
func (el *Element) Attribute(name string) (*string, error) {
attr, err := el.Eval(true, "(n) => this.getAttribute(n)", Array{name})
attr, err := el.Eval("(n) => this.getAttribute(n)", name)
if err != nil {
return nil, err
}
Expand All @@ -256,7 +253,7 @@ func (el *Element) Attribute(name string) (*string, error) {

// Property is similar to the method Property
func (el *Element) Property(name string) (proto.JSON, error) {
prop, err := el.Eval(true, "(n) => this[n]", Array{name})
prop, err := el.Eval("(n) => this[n]", name)
if err != nil {
return proto.JSON{}, err
}
Expand Down Expand Up @@ -333,8 +330,7 @@ func (el *Element) Frame() *Page {

// ContainsElement check if the target is equal or inside the element.
func (el *Element) ContainsElement(target *Element) (bool, error) {
js, args := jsHelper("containsElement", Array{target.ObjectID})
res, err := el.Eval(true, js, args)
res, err := el.EvalWithOptions(jsHelper(js.ContainsElement, Array{target.ObjectID}))
if err != nil {
return false, err
}
Expand All @@ -343,8 +339,7 @@ func (el *Element) ContainsElement(target *Element) (bool, error) {

// Text doc is similar to the method MustText
func (el *Element) Text() (string, error) {
js, jsArgs := jsHelper("text", nil)
str, err := el.Eval(true, js, jsArgs)
str, err := el.EvalWithOptions(jsHelper(js.Text, nil))
if err != nil {
return "", err
}
Expand All @@ -353,7 +348,7 @@ func (el *Element) Text() (string, error) {

// HTML doc is similar to the method MustHTML
func (el *Element) HTML() (string, error) {
str, err := el.Eval(true, `this.outerHTML`, nil)
str, err := el.Eval(`this.outerHTML`)
if err != nil {
return "", err
}
Expand All @@ -362,8 +357,7 @@ func (el *Element) HTML() (string, error) {

// Visible doc is similar to the method MustVisible
func (el *Element) Visible() (bool, error) {
js, jsArgs := jsHelper("visible", nil)
res, err := el.Eval(true, js, jsArgs)
res, err := el.EvalWithOptions(jsHelper(js.Visible, nil))
if err != nil {
return false, err
}
Expand All @@ -372,8 +366,7 @@ func (el *Element) Visible() (bool, error) {

// WaitLoad for element like <img />
func (el *Element) WaitLoad() error {
js, jsArgs := jsHelper("waitLoad", nil)
_, err := el.Eval(true, js, jsArgs)
_, err := el.EvalWithOptions(jsHelper(js.WaitLoad, nil))
return err
}

Expand Down Expand Up @@ -412,9 +405,9 @@ func (el *Element) WaitStable(interval time.Duration) error {
}

// Wait doc is similar to the method MustWait
func (el *Element) Wait(js string, params Array) error {
func (el *Element) Wait(js string, params ...interface{}) error {
return kit.Retry(el.ctx, el.sleeper, func() (bool, error) {
res, err := el.Eval(true, js, params)
res, err := el.Eval(js, params...)
if err != nil {
return true, err
}
Expand All @@ -429,24 +422,22 @@ func (el *Element) Wait(js string, params Array) error {

// WaitVisible doc is similar to the method MustWaitVisible
func (el *Element) WaitVisible() error {
js, jsArgs := jsHelper("visible", nil)
return el.Wait(js, jsArgs)
opts := jsHelper(js.Visible, nil)
return el.Wait(opts.JS, opts.JSArgs...)
}

// WaitInvisible doc is similar to the method MustWaitInvisible
func (el *Element) WaitInvisible() error {
js, jsArgs := jsHelper("invisible", nil)
return el.Wait(js, jsArgs)
opts := jsHelper(js.Invisible, nil)
return el.Wait(opts.JS, opts.JSArgs...)
}

// CanvasToImage get image data of a canvas.
// The default format is image/png.
// The default quality is 0.92.
// doc: https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toDataURL
func (el *Element) CanvasToImage(format string, quality float64) ([]byte, error) {
res, err := el.Eval(true,
`(format, quality) => this.toDataURL(format, quality)`,
Array{format, quality})
res, err := el.Eval(`(format, quality) => this.toDataURL(format, quality)`, format, quality)
if err != nil {
return nil, err
}
Expand All @@ -457,8 +448,7 @@ func (el *Element) CanvasToImage(format string, quality float64) ([]byte, error)

// Resource doc is similar to the method MustResource
func (el *Element) Resource() ([]byte, error) {
js, jsArgs := jsHelper("resource", nil)
src, err := el.Eval(true, js, jsArgs)
src, err := el.EvalWithOptions(jsHelper(js.Resource, nil))
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -539,8 +529,13 @@ func (el *Element) CallContext() (context.Context, proto.Client, string) {
}

// Eval doc is similar to the method MustEval
func (el *Element) Eval(byValue bool, js string, params Array) (*proto.RuntimeRemoteObject, error) {
return el.page.Context(el.ctx, el.ctxCancel).Eval(byValue, el.ObjectID, js, params)
func (el *Element) Eval(js string, params ...interface{}) (*proto.RuntimeRemoteObject, error) {
return el.EvalWithOptions(NewEvalOptions(js, params))
}

// EvalWithOptions of Eval
func (el *Element) EvalWithOptions(opts *EvalOptions) (*proto.RuntimeRemoteObject, error) {
return el.page.Context(el.ctx, el.ctxCancel).EvalWithOptions(opts.This(el.ObjectID))
}

func (el *Element) ensureParentPage(nodeID proto.DOMNodeID, objID proto.RuntimeRemoteObjectID) error {
Expand All @@ -555,7 +550,7 @@ func (el *Element) ensureParentPage(nodeID proto.DOMNodeID, objID proto.RuntimeR
// DFS for the iframe that holds the element
var walk func(page *Page) error
walk = func(page *Page) error {
list, err := page.Elements("", "iframe")
list, err := page.Elements("iframe")
if err != nil {
return err
}
Expand Down
4 changes: 2 additions & 2 deletions element_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -482,12 +482,12 @@ func (s *S) TestFnErr() {
p := s.page.MustNavigate(srcFile("fixtures/click.html"))
el := p.MustElement("button")

_, err := el.Eval(true, "foo()", nil)
_, err := el.Eval("foo()")
s.Error(err)
s.Contains(err.Error(), "ReferenceError: foo is not defined")
s.True(errors.Is(err, rod.ErrEval))

_, err = el.ElementByJS("foo()", nil)
_, err = el.ElementByJS(rod.NewEvalOptions("foo()", nil))
s.Error(err)
s.Contains(err.Error(), "ReferenceError: foo is not defined")
s.True(errors.Is(err, rod.ErrEval))
Expand Down
4 changes: 2 additions & 2 deletions examples_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,11 +199,11 @@ func Example_customize_retry_strategy() {
time.Sleep(time.Second / 2)
return nil
}
el, _ := page.Sleeper(sleeper).Element("", []string{"input"})
el, _ := page.Sleeper(sleeper).Element("input")

// If sleeper is nil page.ElementE will query without retrying.
// If nothing found it will return an error.
el, err := page.Sleeper(nil).Element("", []string{"input"})
el, err := page.Sleeper(nil).Element("input")
if errors.Is(err, rod.ErrElementNotFound) {
fmt.Println("element not found")
} else if err != nil {
Expand Down
4 changes: 2 additions & 2 deletions hijack.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"strings"
"sync"

"github.com/go-rod/rod/lib/assets/js"
"github.com/go-rod/rod/lib/proto"
"github.com/go-rod/rod/lib/utils"
"github.com/tidwall/gjson"
Expand Down Expand Up @@ -493,8 +494,7 @@ func (p *Page) GetDownloadFile(pattern string, resourceType proto.NetworkResourc

u := downloading.URL
if strings.HasPrefix(u, "blob:") {
js, params := jsHelper("fetchAsDataURL", Array{u})
res, e := p.Eval(true, "", js, params)
res, e := p.EvalWithOptions(jsHelper(js.FetchAsDataURL, Array{u}))
if e != nil {
err = e
wg.Done()
Expand Down
3 changes: 2 additions & 1 deletion lib/assets/generate/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ func getDeviceList() string {

func genHelperList(helper string) string {
m := regexp.MustCompile(`\},?\n\n {4}(?:async )?([a-z][^ ]+) \(`).FindAllStringSubmatch(helper, -1)
list := "package js\n\n" +
list := "// generated by running \"go generate\" on project root\n\n" +
"package js\n\n" +
"// NameType type\n" +
"type NameType string\n\n" +
"const (\n"
Expand Down
3 changes: 3 additions & 0 deletions lib/assets/js/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Overview

The `main.go` lists all the function names from `../helper.js`.
2 changes: 2 additions & 0 deletions lib/assets/js/main.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// generated by running "go generate" on project root

package js

// NameType type
Expand Down
Loading

0 comments on commit 79db58d

Please sign in to comment.