1
0
mirror of https://github.com/MontFerret/ferret.git synced 2025-07-15 01:25:00 +02:00

#13 Added WAIT_ELEMENT function

This commit is contained in:
Tim Voronov
2018-09-23 04:33:20 -04:00
parent d98a97fdb1
commit 4df1949b91
15 changed files with 410 additions and 249 deletions

View File

@ -2,11 +2,14 @@ package browser
import (
"context"
"fmt"
"github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/mafredri/cdp"
"github.com/mafredri/cdp/protocol/dom"
"github.com/mafredri/cdp/rpcc"
"strings"
"time"
)
type HtmlDocument struct {
@ -108,3 +111,23 @@ func (doc *HtmlDocument) Compare(other core.Value) int {
return 1
}
}
func (doc *HtmlDocument) WaitForSelector(selector values.String, timeout values.Int) error {
task := NewWaitTask(
doc.client,
fmt.Sprintf(`
el = document.querySelector("%s");
if (el != null) {
return true;
}
return null;
`, selector),
time.Millisecond*time.Duration(timeout),
)
_, err := task.Run()
return err
}

View File

@ -0,0 +1,96 @@
package browser
import (
"context"
"encoding/json"
"fmt"
"github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/mafredri/cdp"
"github.com/mafredri/cdp/protocol/runtime"
"time"
)
type WaitTask struct {
client *cdp.Client
predicate string
timeout time.Duration
}
func NewWaitTask(
client *cdp.Client,
predicate string,
timeout time.Duration,
) *WaitTask {
return &WaitTask{
client,
fmt.Sprintf("((function () {%s})())", predicate),
timeout,
}
}
func (task *WaitTask) Run() (core.Value, error) {
var result core.Value = values.None
var err error
var done bool
timer := time.NewTimer(task.timeout)
for !done {
select {
case <-timer.C:
err = core.ErrTimeout
done = true
default:
out, e := task.exec()
if e != nil {
done = true
timer.Stop()
err = e
break
}
if out != values.None {
timer.Stop()
result = out
done = true
break
}
}
}
return result, err
}
func (task *WaitTask) exec() (core.Value, error) {
args := runtime.NewEvaluateArgs(task.predicate).SetReturnByValue(true)
out, err := task.client.Runtime.Evaluate(context.Background(), args)
if err != nil {
return values.None, err
}
if out.ExceptionDetails != nil {
ex := out.ExceptionDetails
return values.None, core.Error(
core.ErrUnexpected,
fmt.Sprintf("%s %s", ex.Text, *ex.Exception.Description),
)
}
if out.Result.Type != "undefined" {
var o interface{}
err := json.Unmarshal(out.Result.Value, &o)
if err != nil {
return values.None, core.Error(core.ErrUnexpected, err.Error())
}
return values.Parse(o), nil
}
return values.None, nil
}

View File

@ -2,6 +2,8 @@ package driver
import (
"context"
"fmt"
"github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/stdlib/html/driver/browser"
"github.com/MontFerret/ferret/pkg/stdlib/html/driver/http"
@ -19,16 +21,16 @@ func ToContext(ctx context.Context, name string, drv Driver) context.Context {
return context.WithValue(ctx, name, drv)
}
func FromContext(ctx context.Context, name string) Driver {
func FromContext(ctx context.Context, name string) (Driver, error) {
val := ctx.Value(name)
drv, ok := val.(Driver)
if ok {
return drv
return drv, nil
}
return nil
return nil, core.Error(core.ErrNotFound, fmt.Sprintf("%s driver", name))
}
func WithCdpDriver(ctx context.Context, addr string) context.Context {