Expanding Evaluate API

- fixed issues with Evaluate
- added examples/eval
This commit is contained in:
Kenneth Shaw 2017-02-08 14:27:39 +07:00
parent 8c2c95f9a2
commit 465e7becad
10 changed files with 294 additions and 104 deletions

View File

@ -2,6 +2,7 @@ package runtime
import ( import (
"errors" "errors"
"fmt"
"github.com/mailru/easyjson" "github.com/mailru/easyjson"
"github.com/mailru/easyjson/jlexer" "github.com/mailru/easyjson/jlexer"
@ -181,6 +182,13 @@ type ExceptionDetails struct {
ExecutionContextID ExecutionContextID `json:"executionContextId,omitempty"` // Identifier of the context where exception happened. ExecutionContextID ExecutionContextID `json:"executionContextId,omitempty"` // Identifier of the context where exception happened.
} }
// Error satisfies the error interface.
func (e *ExceptionDetails) Error() string {
// TODO: watch script parsed events and match the ExceptionDetails.ScriptID
// to the name/location of the actual code and display here
return fmt.Sprintf("encountered exception '%s' (%d:%d)", e.Text, e.LineNumber, e.ColumnNumber)
}
// CallFrame stack entry for runtime errors and assertions. // CallFrame stack entry for runtime errors and assertions.
type CallFrame struct { type CallFrame struct {
FunctionName string `json:"functionName,omitempty"` // JavaScript function name. FunctionName string `json:"functionName,omitempty"` // JavaScript function name.

View File

@ -56,6 +56,7 @@ const (
// - add special unmarshaler to NodeId, BackendNodeId, FrameId to handle values from older (v1.1) protocol versions. -- NOTE: this might need to be applied to more types, such as network.LoaderId // - add special unmarshaler to NodeId, BackendNodeId, FrameId to handle values from older (v1.1) protocol versions. -- NOTE: this might need to be applied to more types, such as network.LoaderId
// - rename 'Input.GestureSourceType' -> 'Input.GestureType'. // - rename 'Input.GestureSourceType' -> 'Input.GestureType'.
// - rename CSS.CSS* types. // - rename CSS.CSS* types.
// - add Error() method to 'Runtime.ExceptionDetails' type so that it can be used as error.
func FixupDomains(domains []*internal.Domain) { func FixupDomains(domains []*internal.Domain) {
// method type // method type
methodType := &internal.Type{ methodType := &internal.Type{
@ -309,9 +310,14 @@ func FixupDomains(domains []*internal.Domain) {
case internal.DomainRuntime: case internal.DomainRuntime:
var types []*internal.Type var types []*internal.Type
for _, t := range d.Types { for _, t := range d.Types {
if t.ID == "Timestamp" { switch t.ID {
case "Timestamp":
continue continue
case "ExceptionDetails":
t.Extra += templates.ExtraExceptionDetailsTemplate()
} }
types = append(types, t) types = append(types, t)
} }
d.Types = types d.Types = types

View File

@ -195,6 +195,17 @@ func (t *{%s= typ %}) UnmarshalJSON(buf []byte) error {
} }
{% endfunc %} {% endfunc %}
// ExtraExceptionDetailsTemplate is a special template for the Runtime.ExceptionDetails type that
// defines the standard error interface.
{% func ExtraExceptionDetailsTemplate() %}
// Error satisfies the error interface.
func (e *ExceptionDetails) Error() string {
// TODO: watch script parsed events and match the ExceptionDetails.ScriptID
// to the name/location of the actual code and display here
return fmt.Sprintf("encountered exception '%s' (%d:%d)", e.Text, e.LineNumber, e.ColumnNumber)
}
{% endfunc %}
// ExtraCDPTypes is the template for additional internal type // ExtraCDPTypes is the template for additional internal type
// declarations. // declarations.
{% func ExtraCDPTypes() %} {% func ExtraCDPTypes() %}

View File

@ -420,12 +420,55 @@ func ExtraFixStringUnmarshaler(typ, parseFunc, extra string) string {
//line templates/extra.qtpl:196 //line templates/extra.qtpl:196
} }
// ExtraExceptionDetailsTemplate is a special template for the Runtime.ExceptionDetails type that
// defines the standard error interface.
//line templates/extra.qtpl:200
func StreamExtraExceptionDetailsTemplate(qw422016 *qt422016.Writer) {
//line templates/extra.qtpl:200
qw422016.N().S(`
// Error satisfies the error interface.
func (e *ExceptionDetails) Error() string {
// TODO: watch script parsed events and match the ExceptionDetails.ScriptID
// to the name/location of the actual code and display here
return fmt.Sprintf("encountered exception '%s' (%d:%d)", e.Text, e.LineNumber, e.ColumnNumber)
}
`)
//line templates/extra.qtpl:207
}
//line templates/extra.qtpl:207
func WriteExtraExceptionDetailsTemplate(qq422016 qtio422016.Writer) {
//line templates/extra.qtpl:207
qw422016 := qt422016.AcquireWriter(qq422016)
//line templates/extra.qtpl:207
StreamExtraExceptionDetailsTemplate(qw422016)
//line templates/extra.qtpl:207
qt422016.ReleaseWriter(qw422016)
//line templates/extra.qtpl:207
}
//line templates/extra.qtpl:207
func ExtraExceptionDetailsTemplate() string {
//line templates/extra.qtpl:207
qb422016 := qt422016.AcquireByteBuffer()
//line templates/extra.qtpl:207
WriteExtraExceptionDetailsTemplate(qb422016)
//line templates/extra.qtpl:207
qs422016 := string(qb422016.B)
//line templates/extra.qtpl:207
qt422016.ReleaseByteBuffer(qb422016)
//line templates/extra.qtpl:207
return qs422016
//line templates/extra.qtpl:207
}
// ExtraCDPTypes is the template for additional internal type // ExtraCDPTypes is the template for additional internal type
// declarations. // declarations.
//line templates/extra.qtpl:200 //line templates/extra.qtpl:211
func StreamExtraCDPTypes(qw422016 *qt422016.Writer) { func StreamExtraCDPTypes(qw422016 *qt422016.Writer) {
//line templates/extra.qtpl:200 //line templates/extra.qtpl:211
qw422016.N().S(` qw422016.N().S(`
// Error satisfies the error interface. // Error satisfies the error interface.
@ -448,49 +491,49 @@ type FrameHandler interface {
// Empty is an empty JSON object message. // Empty is an empty JSON object message.
var Empty = easyjson.RawMessage(`) var Empty = easyjson.RawMessage(`)
//line templates/extra.qtpl:200 //line templates/extra.qtpl:211
qw422016.N().S("`") qw422016.N().S("`")
//line templates/extra.qtpl:200 //line templates/extra.qtpl:211
qw422016.N().S(`{}`) qw422016.N().S(`{}`)
//line templates/extra.qtpl:200 //line templates/extra.qtpl:211
qw422016.N().S("`") qw422016.N().S("`")
//line templates/extra.qtpl:200 //line templates/extra.qtpl:211
qw422016.N().S(`) qw422016.N().S(`)
`) `)
//line templates/extra.qtpl:222 //line templates/extra.qtpl:233
} }
//line templates/extra.qtpl:222 //line templates/extra.qtpl:233
func WriteExtraCDPTypes(qq422016 qtio422016.Writer) { func WriteExtraCDPTypes(qq422016 qtio422016.Writer) {
//line templates/extra.qtpl:222 //line templates/extra.qtpl:233
qw422016 := qt422016.AcquireWriter(qq422016) qw422016 := qt422016.AcquireWriter(qq422016)
//line templates/extra.qtpl:222 //line templates/extra.qtpl:233
StreamExtraCDPTypes(qw422016) StreamExtraCDPTypes(qw422016)
//line templates/extra.qtpl:222 //line templates/extra.qtpl:233
qt422016.ReleaseWriter(qw422016) qt422016.ReleaseWriter(qw422016)
//line templates/extra.qtpl:222 //line templates/extra.qtpl:233
} }
//line templates/extra.qtpl:222 //line templates/extra.qtpl:233
func ExtraCDPTypes() string { func ExtraCDPTypes() string {
//line templates/extra.qtpl:222 //line templates/extra.qtpl:233
qb422016 := qt422016.AcquireByteBuffer() qb422016 := qt422016.AcquireByteBuffer()
//line templates/extra.qtpl:222 //line templates/extra.qtpl:233
WriteExtraCDPTypes(qb422016) WriteExtraCDPTypes(qb422016)
//line templates/extra.qtpl:222 //line templates/extra.qtpl:233
qs422016 := string(qb422016.B) qs422016 := string(qb422016.B)
//line templates/extra.qtpl:222 //line templates/extra.qtpl:233
qt422016.ReleaseByteBuffer(qb422016) qt422016.ReleaseByteBuffer(qb422016)
//line templates/extra.qtpl:222 //line templates/extra.qtpl:233
return qs422016 return qs422016
//line templates/extra.qtpl:222 //line templates/extra.qtpl:233
} }
// ExtraUtilTemplate generates the decode func for the Message type. // ExtraUtilTemplate generates the decode func for the Message type.
//line templates/extra.qtpl:225 //line templates/extra.qtpl:236
func StreamExtraUtilTemplate(qw422016 *qt422016.Writer, domains []*internal.Domain) { func StreamExtraUtilTemplate(qw422016 *qt422016.Writer, domains []*internal.Domain) {
//line templates/extra.qtpl:225 //line templates/extra.qtpl:236
qw422016.N().S(` qw422016.N().S(`
type empty struct{} type empty struct{}
var emptyVal = &empty{} var emptyVal = &empty{}
@ -499,66 +542,66 @@ var emptyVal = &empty{}
func UnmarshalMessage(msg *cdp.Message) (interface{}, error) { func UnmarshalMessage(msg *cdp.Message) (interface{}, error) {
var v easyjson.Unmarshaler var v easyjson.Unmarshaler
switch msg.Method {`) switch msg.Method {`)
//line templates/extra.qtpl:232 //line templates/extra.qtpl:243
for _, d := range domains { for _, d := range domains {
//line templates/extra.qtpl:232 //line templates/extra.qtpl:243
for _, c := range d.Commands { for _, c := range d.Commands {
//line templates/extra.qtpl:232 //line templates/extra.qtpl:243
qw422016.N().S(` qw422016.N().S(`
case cdp.`) case cdp.`)
//line templates/extra.qtpl:233 //line templates/extra.qtpl:244
qw422016.N().S(c.CommandMethodType(d)) qw422016.N().S(c.CommandMethodType(d))
//line templates/extra.qtpl:233 //line templates/extra.qtpl:244
qw422016.N().S(`:`) qw422016.N().S(`:`)
//line templates/extra.qtpl:233 //line templates/extra.qtpl:244
if len(c.Returns) == 0 { if len(c.Returns) == 0 {
//line templates/extra.qtpl:233 //line templates/extra.qtpl:244
qw422016.N().S(` qw422016.N().S(`
return emptyVal, nil`) return emptyVal, nil`)
//line templates/extra.qtpl:234 //line templates/extra.qtpl:245
} else { } else {
//line templates/extra.qtpl:234 //line templates/extra.qtpl:245
qw422016.N().S(` qw422016.N().S(`
v = new(`) v = new(`)
//line templates/extra.qtpl:235 //line templates/extra.qtpl:246
qw422016.N().S(d.PackageRefName()) qw422016.N().S(d.PackageRefName())
//line templates/extra.qtpl:235 //line templates/extra.qtpl:246
qw422016.N().S(`.`) qw422016.N().S(`.`)
//line templates/extra.qtpl:235 //line templates/extra.qtpl:246
qw422016.N().S(c.CommandReturnsType()) qw422016.N().S(c.CommandReturnsType())
//line templates/extra.qtpl:235 //line templates/extra.qtpl:246
qw422016.N().S(`)`) qw422016.N().S(`)`)
//line templates/extra.qtpl:235 //line templates/extra.qtpl:246
} }
//line templates/extra.qtpl:235 //line templates/extra.qtpl:246
qw422016.N().S(` qw422016.N().S(`
`) `)
//line templates/extra.qtpl:236 //line templates/extra.qtpl:247
} }
//line templates/extra.qtpl:236 //line templates/extra.qtpl:247
for _, e := range d.Events { for _, e := range d.Events {
//line templates/extra.qtpl:236 //line templates/extra.qtpl:247
qw422016.N().S(` qw422016.N().S(`
case cdp.`) case cdp.`)
//line templates/extra.qtpl:237 //line templates/extra.qtpl:248
qw422016.N().S(e.EventMethodType(d)) qw422016.N().S(e.EventMethodType(d))
//line templates/extra.qtpl:237 //line templates/extra.qtpl:248
qw422016.N().S(`: qw422016.N().S(`:
v = new(`) v = new(`)
//line templates/extra.qtpl:238 //line templates/extra.qtpl:249
qw422016.N().S(d.PackageRefName()) qw422016.N().S(d.PackageRefName())
//line templates/extra.qtpl:238 //line templates/extra.qtpl:249
qw422016.N().S(`.`) qw422016.N().S(`.`)
//line templates/extra.qtpl:238 //line templates/extra.qtpl:249
qw422016.N().S(e.EventType()) qw422016.N().S(e.EventType())
//line templates/extra.qtpl:238 //line templates/extra.qtpl:249
qw422016.N().S(`) qw422016.N().S(`)
`) `)
//line templates/extra.qtpl:239 //line templates/extra.qtpl:250
} }
//line templates/extra.qtpl:239 //line templates/extra.qtpl:250
} }
//line templates/extra.qtpl:239 //line templates/extra.qtpl:250
qw422016.N().S(`} qw422016.N().S(`}
var buf easyjson.RawMessage var buf easyjson.RawMessage
@ -581,69 +624,69 @@ func UnmarshalMessage(msg *cdp.Message) (interface{}, error) {
return v, nil return v, nil
} }
`) `)
//line templates/extra.qtpl:260 //line templates/extra.qtpl:271
} }
//line templates/extra.qtpl:260 //line templates/extra.qtpl:271
func WriteExtraUtilTemplate(qq422016 qtio422016.Writer, domains []*internal.Domain) { func WriteExtraUtilTemplate(qq422016 qtio422016.Writer, domains []*internal.Domain) {
//line templates/extra.qtpl:260 //line templates/extra.qtpl:271
qw422016 := qt422016.AcquireWriter(qq422016) qw422016 := qt422016.AcquireWriter(qq422016)
//line templates/extra.qtpl:260 //line templates/extra.qtpl:271
StreamExtraUtilTemplate(qw422016, domains) StreamExtraUtilTemplate(qw422016, domains)
//line templates/extra.qtpl:260 //line templates/extra.qtpl:271
qt422016.ReleaseWriter(qw422016) qt422016.ReleaseWriter(qw422016)
//line templates/extra.qtpl:260 //line templates/extra.qtpl:271
} }
//line templates/extra.qtpl:260 //line templates/extra.qtpl:271
func ExtraUtilTemplate(domains []*internal.Domain) string { func ExtraUtilTemplate(domains []*internal.Domain) string {
//line templates/extra.qtpl:260 //line templates/extra.qtpl:271
qb422016 := qt422016.AcquireByteBuffer() qb422016 := qt422016.AcquireByteBuffer()
//line templates/extra.qtpl:260 //line templates/extra.qtpl:271
WriteExtraUtilTemplate(qb422016, domains) WriteExtraUtilTemplate(qb422016, domains)
//line templates/extra.qtpl:260 //line templates/extra.qtpl:271
qs422016 := string(qb422016.B) qs422016 := string(qb422016.B)
//line templates/extra.qtpl:260 //line templates/extra.qtpl:271
qt422016.ReleaseByteBuffer(qb422016) qt422016.ReleaseByteBuffer(qb422016)
//line templates/extra.qtpl:260 //line templates/extra.qtpl:271
return qs422016 return qs422016
//line templates/extra.qtpl:260 //line templates/extra.qtpl:271
} }
//line templates/extra.qtpl:262 //line templates/extra.qtpl:273
func StreamExtraMethodTypeDomainDecoder(qw422016 *qt422016.Writer) { func StreamExtraMethodTypeDomainDecoder(qw422016 *qt422016.Writer) {
//line templates/extra.qtpl:262 //line templates/extra.qtpl:273
qw422016.N().S(` qw422016.N().S(`
// Domain returns the Chrome Debugging Protocol domain of the event or command. // Domain returns the Chrome Debugging Protocol domain of the event or command.
func (t MethodType) Domain() string { func (t MethodType) Domain() string {
return string(t[:strings.IndexByte(string(t), '.')]) return string(t[:strings.IndexByte(string(t), '.')])
} }
`) `)
//line templates/extra.qtpl:267 //line templates/extra.qtpl:278
} }
//line templates/extra.qtpl:267 //line templates/extra.qtpl:278
func WriteExtraMethodTypeDomainDecoder(qq422016 qtio422016.Writer) { func WriteExtraMethodTypeDomainDecoder(qq422016 qtio422016.Writer) {
//line templates/extra.qtpl:267 //line templates/extra.qtpl:278
qw422016 := qt422016.AcquireWriter(qq422016) qw422016 := qt422016.AcquireWriter(qq422016)
//line templates/extra.qtpl:267 //line templates/extra.qtpl:278
StreamExtraMethodTypeDomainDecoder(qw422016) StreamExtraMethodTypeDomainDecoder(qw422016)
//line templates/extra.qtpl:267 //line templates/extra.qtpl:278
qt422016.ReleaseWriter(qw422016) qt422016.ReleaseWriter(qw422016)
//line templates/extra.qtpl:267 //line templates/extra.qtpl:278
} }
//line templates/extra.qtpl:267 //line templates/extra.qtpl:278
func ExtraMethodTypeDomainDecoder() string { func ExtraMethodTypeDomainDecoder() string {
//line templates/extra.qtpl:267 //line templates/extra.qtpl:278
qb422016 := qt422016.AcquireByteBuffer() qb422016 := qt422016.AcquireByteBuffer()
//line templates/extra.qtpl:267 //line templates/extra.qtpl:278
WriteExtraMethodTypeDomainDecoder(qb422016) WriteExtraMethodTypeDomainDecoder(qb422016)
//line templates/extra.qtpl:267 //line templates/extra.qtpl:278
qs422016 := string(qb422016.B) qs422016 := string(qb422016.B)
//line templates/extra.qtpl:267 //line templates/extra.qtpl:278
qt422016.ReleaseByteBuffer(qb422016) qt422016.ReleaseByteBuffer(qb422016)
//line templates/extra.qtpl:267 //line templates/extra.qtpl:278
return qs422016 return qs422016
//line templates/extra.qtpl:267 //line templates/extra.qtpl:278
} }

93
eval.go Normal file
View File

@ -0,0 +1,93 @@
package chromedp
import (
"context"
"encoding/json"
"github.com/knq/chromedp/cdp"
rundom "github.com/knq/chromedp/cdp/runtime"
)
// Evaluate evaluates the supplied Javascript expression, attempting to
// unmarshal the resulting value into res.
//
// If res is a **chromedp/cdp/runtime.RemoteObject, then it will be set to the
// raw, returned RuntimeObject, Otherwise, the result value be json.Unmarshal'd
// to res.
func Evaluate(expression string, res interface{}, opts ...EvaluateOption) Action {
if res == nil {
panic("res cannot be nil")
}
return ActionFunc(func(ctxt context.Context, h cdp.FrameHandler) error {
var err error
// check if we want a 'raw' result
obj, raw := res.(**rundom.RemoteObject)
// set up parameters
p := rundom.Evaluate(expression)
if !raw {
p = p.WithReturnByValue(true)
}
// apply opts
for _, o := range opts {
p = o(p)
}
// evaluate
v, exp, err := p.Do(ctxt, h)
if err != nil {
return err
}
if exp != nil {
return exp
}
if raw {
*obj = v
return nil
}
// unmarshal
return json.Unmarshal(v.Value, res)
})
}
// EvaluateOption is an Evaluate call option.
type EvaluateOption func(*rundom.EvaluateParams) *rundom.EvaluateParams
// EvalObjectGroup is a Evaluate option to set the object group.
func EvalObjectGroup(objectGroup string) EvaluateOption {
return func(p *rundom.EvaluateParams) *rundom.EvaluateParams {
return p.WithObjectGroup(objectGroup)
}
}
// EvalWithCommandLineAPI is an Evaluate option to include the DevTools Command
// Line API.
//
// Note: this should not be used with any untrusted code.
func EvalWithCommandLineAPI(p *rundom.EvaluateParams) *rundom.EvaluateParams {
return p.WithIncludeCommandLineAPI(true)
}
// EvalSilent is a Evaluate option that will cause script evaluation to ignore
// exceptions.
func EvalSilent(p *rundom.EvaluateParams) *rundom.EvaluateParams {
return p.WithSilent(true)
}
// EvalAsValue is a Evaluate option that will case the script to encode its
// result as a value.
func EvalAsValue(p *rundom.EvaluateParams) *rundom.EvaluateParams {
return p.WithReturnByValue(true)
}
// EvaluateAsDevTools evaluates a Javascript expression in the same
//
// Note: this should not be used with any untrusted code.
func EvaluateAsDevTools(expression string) Action {
return Evaluate(expression, EvalObjectGroup("console"), EvalWithCommandLineAPI)
}

2
examples/eval/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
eval
eval.exe

47
examples/eval/main.go Normal file
View File

@ -0,0 +1,47 @@
package main
import (
"context"
"log"
cdp "github.com/knq/chromedp"
)
func main() {
var err error
// create context
ctxt, cancel := context.WithCancel(context.Background())
defer cancel()
// create chrome instance
c, err := cdp.New(ctxt)
if err != nil {
log.Fatal(err)
}
// run task list
var res []string
err = c.Run(ctxt, cdp.Tasks{
cdp.Navigate(`https://www.brank.as`),
cdp.WaitVisible(`#footer`, cdp.ByID),
cdp.Evaluate(`Object.keys(window);`, &res),
})
if err != nil {
log.Fatal(err)
}
// shutdown chrome
err = c.Shutdown(ctxt)
if err != nil {
log.Fatal(err)
}
// wait for chrome to finish
err = c.Wait()
if err != nil {
log.Fatal(err)
}
log.Printf("window object keys: %v", res)
}

22
nav.go
View File

@ -4,7 +4,6 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"log"
"github.com/knq/chromedp/cdp" "github.com/knq/chromedp/cdp"
"github.com/knq/chromedp/cdp/page" "github.com/knq/chromedp/cdp/page"
@ -121,25 +120,6 @@ func Stop() Action {
return page.StopLoading() return page.StopLoading()
} }
// Evaluate evaluates a script.
func Evaluate(expression string, res **rundom.RemoteObject) Action {
if res == nil {
panic("res cannot be nil")
}
return ActionFunc(func(ctxt context.Context, h cdp.FrameHandler) error {
v, exp, err := rundom.Evaluate(expression).Do(ctxt, h)
if err != nil {
return err
}
if exp != nil {
log.Printf(">>> GOT EXECPTION: %v", exp)
}
*res = v
return nil
})
}
// Location retrieves the URL location. // Location retrieves the URL location.
func Location(urlstr *string) Action { func Location(urlstr *string) Action {
if urlstr == nil { if urlstr == nil {
@ -151,7 +131,7 @@ func Location(urlstr *string) Action {
return err return err
} }
if exp != nil { if exp != nil {
return fmt.Errorf("got exception evaluating script: %#v", exp) return exp
} }
if res.Type != rundom.TypeString || len(res.Value) < 2 { if res.Type != rundom.TypeString || len(res.Value) < 2 {
return fmt.Errorf("expected string of at least length 2, got %s length %d", res.Subtype, len(res.Value)) return fmt.Errorf("expected string of at least length 2, got %s length %d", res.Subtype, len(res.Value))

View File

@ -142,7 +142,7 @@ func Value(sel interface{}, value *string, opts ...QueryOption) Action {
return err return err
} }
if exp != nil { if exp != nil {
return fmt.Errorf("got exception evaluating script: %#v", exp) return exp
} }
if res.Type != rundom.TypeString || len(res.Value) < 2 { if res.Type != rundom.TypeString || len(res.Value) < 2 {
return fmt.Errorf("expected string of at least length 2, got %s length %d", res.Subtype, len(res.Value)) return fmt.Errorf("expected string of at least length 2, got %s length %d", res.Subtype, len(res.Value))
@ -170,7 +170,7 @@ func SetValue(sel interface{}, value string, opts ...QueryOption) Action {
return err return err
} }
if exp != nil { if exp != nil {
return fmt.Errorf("got exception evaluating script: %#v", exp) return exp
} }
if res.Type != rundom.TypeString || len(res.Value) < 2 { if res.Type != rundom.TypeString || len(res.Value) < 2 {
return fmt.Errorf("expected string of at least length 2, got %s length %d", res.Subtype, len(res.Value)) return fmt.Errorf("expected string of at least length 2, got %s length %d", res.Subtype, len(res.Value))
@ -199,7 +199,7 @@ func Text(sel interface{}, text *string, opts ...QueryOption) Action {
return err return err
} }
if exp != nil { if exp != nil {
return fmt.Errorf("got exception evaluating script: %#v", exp) return exp
} }
if res.Type != rundom.TypeString || len(res.Value) < 2 { if res.Type != rundom.TypeString || len(res.Value) < 2 {
return fmt.Errorf("expected string of at least length 2, got %s length %d", res.Subtype, len(res.Value)) return fmt.Errorf("expected string of at least length 2, got %s length %d", res.Subtype, len(res.Value))
@ -378,7 +378,7 @@ func Screenshot(sel interface{}, picbuf *[]byte, opts ...QueryOption) Action {
return err return err
} }
if exp != nil { if exp != nil {
return fmt.Errorf("got exception evaluating script: %#v", exp) return exp
} }
if res.Type != rundom.TypeString || len(res.Value) < 2 { if res.Type != rundom.TypeString || len(res.Value) < 2 {
return fmt.Errorf("expected string of at least length 2, got %s length %d", res.Subtype, len(res.Value)) return fmt.Errorf("expected string of at least length 2, got %s length %d", res.Subtype, len(res.Value))
@ -438,7 +438,7 @@ func Submit(sel interface{}, opts ...QueryOption) Action {
return err return err
} }
if exp != nil { if exp != nil {
return fmt.Errorf("got exception evaluating script: %#v", exp) return exp
} }
if res.Type != rundom.TypeString || len(res.Value) < 2 { if res.Type != rundom.TypeString || len(res.Value) < 2 {
return fmt.Errorf("expected string of at least length 2, got %s length %d", res.Subtype, len(res.Value)) return fmt.Errorf("expected string of at least length 2, got %s length %d", res.Subtype, len(res.Value))