diff --git a/Makefile b/Makefile
index bfdf27b6..e43d1599 100644
--- a/Makefile
+++ b/Makefile
@@ -31,7 +31,7 @@ cover:
e2e:
go run ${DIR_E2E}/main.go --tests ${DIR_E2E}/tests --pages ${DIR_E2E}/pages
- # --filter=e2e/tests/dynamic/**/inner_text/*.fql
+ # --filter=e2e/tests/**/xpath/*.fql
bench:
go test -run=XXX -bench=. ${DIR_PKG}/...
diff --git a/pkg/drivers/cdp/document.go b/pkg/drivers/cdp/document.go
index 0c01e96c..9a0a92c7 100644
--- a/pkg/drivers/cdp/document.go
+++ b/pkg/drivers/cdp/document.go
@@ -326,18 +326,10 @@ func (doc *HTMLDocument) ClickBySelector(ctx context.Context, selector values.St
}
func (doc *HTMLDocument) ClickBySelectorAll(ctx context.Context, selector values.String) (values.Boolean, error) {
- found, err := doc.client.DOM.QuerySelectorAll(ctx, dom.NewQuerySelectorAllArgs(doc.element.id.nodeID, selector.String()))
-
- if err != nil {
+ if err := doc.input.ClickBySelectorAll(ctx, doc.element.id.nodeID, selector); err != nil {
return values.False, err
}
- for _, nodeID := range found.NodeIDs {
- if err := doc.input.ClickByNodeID(ctx, nodeID); err != nil {
- return values.False, err
- }
- }
-
return values.True, nil
}
@@ -358,7 +350,7 @@ func (doc *HTMLDocument) MoveMouseBySelector(ctx context.Context, selector value
}
func (doc *HTMLDocument) MoveMouseByXY(ctx context.Context, x, y values.Float) error {
- return doc.input.MoveMouse(ctx, x, y)
+ return doc.input.MoveMouseByXY(ctx, x, y)
}
func (doc *HTMLDocument) WaitForElement(ctx context.Context, selector values.String, when drivers.WaitEvent) error {
@@ -521,7 +513,7 @@ func (doc *HTMLDocument) ScrollBySelector(ctx context.Context, selector values.S
}
func (doc *HTMLDocument) ScrollByXY(ctx context.Context, x, y values.Float) error {
- return doc.input.Scroll(ctx, x, y)
+ return doc.input.ScrollByXY(ctx, x, y)
}
func (doc *HTMLDocument) loadChildren(ctx context.Context) (value core.Value, e error) {
diff --git a/pkg/drivers/cdp/element.go b/pkg/drivers/cdp/element.go
index fc06494e..6e0391c7 100644
--- a/pkg/drivers/cdp/element.go
+++ b/pkg/drivers/cdp/element.go
@@ -576,7 +576,7 @@ func (el *HTMLElement) XPath(ctx context.Context, expression values.String) (res
return values.None, err
}
- out, err := el.exec.CallFunction(ctx, templates.XPath(),
+ out, err := el.exec.EvalWithArgumentsAndReturnReference(ctx, templates.XPath(),
runtime.CallArgument{
ObjectID: &el.id.objectID,
},
@@ -593,25 +593,7 @@ func (el *HTMLElement) XPath(ctx context.Context, expression values.String) (res
// checking whether it's actually an array
if typeName == "object" {
- isArrayRes, err := el.exec.CallFunction(ctx, `
- (target) => Array.isArray(target)
- `,
- runtime.CallArgument{
- ObjectID: out.ObjectID,
- },
- )
-
- if err != nil {
- return values.None, err
- }
-
- isArray, err := eval.Unmarshal(&isArrayRes)
-
- if err != nil {
- return values.None, err
- }
-
- if isArray == values.True {
+ if out.ClassName != nil && *out.ClassName == "Array" {
typeName = "array"
}
}
@@ -745,7 +727,7 @@ func (el *HTMLElement) GetInnerTextBySelector(ctx context.Context, selector valu
return values.EmptyString, drivers.ErrDetached
}
- out, err := el.exec.EvalWithValue(ctx, templates.GetInnerTextBySelector(selector.String()))
+ out, err := el.exec.EvalWithReturnValue(ctx, templates.GetInnerTextBySelector(selector.String()))
if err != nil {
return values.EmptyString, err
@@ -767,7 +749,7 @@ func (el *HTMLElement) GetInnerTextBySelectorAll(ctx context.Context, selector v
return values.NewArray(0), drivers.ErrDetached
}
- out, err := el.exec.EvalWithValue(ctx, templates.GetInnerTextBySelectorAll(selector.String()))
+ out, err := el.exec.EvalWithReturnValue(ctx, templates.GetInnerTextBySelectorAll(selector.String()))
if err != nil {
return values.NewArray(0), err
@@ -811,7 +793,7 @@ func (el *HTMLElement) GetInnerHTMLBySelector(ctx context.Context, selector valu
return values.EmptyString, drivers.ErrDetached
}
- out, err := el.exec.EvalWithValue(ctx, templates.GetInnerHTMLBySelector(selector.String()))
+ out, err := el.exec.EvalWithReturnValue(ctx, templates.GetInnerHTMLBySelector(selector.String()))
if err != nil {
return values.EmptyString, err
@@ -833,7 +815,7 @@ func (el *HTMLElement) GetInnerHTMLBySelectorAll(ctx context.Context, selector v
return values.NewArray(0), drivers.ErrDetached
}
- out, err := el.exec.EvalWithValue(ctx, templates.GetInnerHTMLBySelectorAll(selector.String()))
+ out, err := el.exec.EvalWithReturnValue(ctx, templates.GetInnerHTMLBySelectorAll(selector.String()))
if err != nil {
return values.NewArray(0), err
@@ -966,7 +948,7 @@ func (el *HTMLElement) WaitForStyle(ctx context.Context, name values.String, val
}
func (el *HTMLElement) Click(ctx context.Context) (values.Boolean, error) {
- if err := el.input.ClickByNodeID(ctx, el.id.nodeID); err != nil {
+ if err := el.input.Click(ctx, el.id.objectID); err != nil {
return values.False, err
}
@@ -978,19 +960,19 @@ func (el *HTMLElement) Input(ctx context.Context, value core.Value, delay values
return core.Error(core.ErrInvalidOperation, "element is not an element.")
}
- return el.input.TypeByNodeID(ctx, el.id.nodeID, value, delay)
+ return el.input.Type(ctx, el.id.objectID, value, delay)
}
func (el *HTMLElement) Select(ctx context.Context, value *values.Array) (*values.Array, error) {
- return el.input.SelectByNodeID(ctx, el.id.nodeID, value)
+ return el.input.Select(ctx, el.id.objectID, value)
}
func (el *HTMLElement) ScrollIntoView(ctx context.Context) error {
- return el.input.ScrollIntoViewByNodeID(ctx, el.id.nodeID)
+ return el.input.ScrollIntoView(ctx, el.id.objectID)
}
func (el *HTMLElement) Hover(ctx context.Context) error {
- return el.input.MoveMouseByNodeID(ctx, el.id.nodeID)
+ return el.input.MoveMouse(ctx, el.id.objectID)
}
func (el *HTMLElement) IsDetached() values.Boolean {
diff --git a/pkg/drivers/cdp/eval/context.go b/pkg/drivers/cdp/eval/context.go
index ccb7449d..06ec096d 100644
--- a/pkg/drivers/cdp/eval/context.go
+++ b/pkg/drivers/cdp/eval/context.go
@@ -47,7 +47,27 @@ func (ec *ExecutionContext) Eval(ctx context.Context, exp string) error {
return err
}
-func (ec *ExecutionContext) EvalWithValue(ctx context.Context, exp string) (core.Value, error) {
+func (ec *ExecutionContext) EvalWithArguments(ctx context.Context, exp string, args ...runtime.CallArgument) error {
+ _, err := ec.evalWithArgumentsInternal(ctx, exp, args, false)
+
+ return err
+}
+
+func (ec *ExecutionContext) EvalWithArgumentsAndReturnValue(ctx context.Context, exp string, args ...runtime.CallArgument) (core.Value, error) {
+ out, err := ec.evalWithArgumentsInternal(ctx, exp, args, true)
+
+ if err != nil {
+ return values.None, err
+ }
+
+ return Unmarshal(&out)
+}
+
+func (ec *ExecutionContext) EvalWithArgumentsAndReturnReference(ctx context.Context, exp string, args ...runtime.CallArgument) (runtime.RemoteObject, error) {
+ return ec.evalWithArgumentsInternal(ctx, exp, args, false)
+}
+
+func (ec *ExecutionContext) EvalWithReturnValue(ctx context.Context, exp string) (core.Value, error) {
return ec.evalWithValueInternal(
ctx,
runtime.
@@ -56,6 +76,15 @@ func (ec *ExecutionContext) EvalWithValue(ctx context.Context, exp string) (core
)
}
+func (ec *ExecutionContext) EvalWithReturnReference(ctx context.Context, exp string) (runtime.RemoteObject, error) {
+ return ec.evalInternal(
+ ctx,
+ runtime.
+ NewEvaluateArgs(PrepareEval(exp)).
+ SetReturnByValue(false),
+ )
+}
+
func (ec *ExecutionContext) EvalAsync(ctx context.Context, exp string) (core.Value, error) {
return ec.evalWithValueInternal(
ctx,
@@ -66,20 +95,6 @@ func (ec *ExecutionContext) EvalAsync(ctx context.Context, exp string) (core.Val
)
}
-func (ec *ExecutionContext) ResolveRemoteObject(ctx context.Context, exp string) (runtime.RemoteObject, error) {
- res, err := ec.evalInternal(ctx, runtime.NewEvaluateArgs(PrepareEval(exp)))
-
- if err != nil {
- return runtime.RemoteObject{}, err
- }
-
- if res.ObjectID == nil {
- return runtime.RemoteObject{}, errors.Wrap(core.ErrUnexpected, "unable to resolve remote object")
- }
-
- return res, nil
-}
-
func (ec *ExecutionContext) CallMethod(
ctx context.Context,
objectID runtime.RemoteObjectID,
@@ -103,8 +118,10 @@ func (ec *ExecutionContext) CallMethod(
return nil, err
}
- if found.ExceptionDetails != nil {
- return nil, found.ExceptionDetails
+ err = ec.handleException(found.ExceptionDetails)
+
+ if err != nil {
+ return nil, err
}
if found.Result.ObjectID == nil {
@@ -195,8 +212,10 @@ func (ec *ExecutionContext) DispatchEvent(
return values.False, nil
}
- if evt.ExceptionDetails != nil {
- return values.False, evt.ExceptionDetails
+ err = ec.handleException(evt.ExceptionDetails)
+
+ if err != nil {
+ return values.False, nil
}
if evt.Result.ObjectID == nil {
@@ -226,8 +245,45 @@ func (ec *ExecutionContext) DispatchEvent(
return values.True, nil
}
-func (ec *ExecutionContext) CallFunction(ctx context.Context, declaration string, args ...runtime.CallArgument) (runtime.RemoteObject, error) {
- cfArgs := runtime.NewCallFunctionOnArgs(declaration).SetArguments(args)
+func (ec *ExecutionContext) ResolveRemoteObject(ctx context.Context, exp string) (runtime.RemoteObject, error) {
+ res, err := ec.evalInternal(ctx, runtime.NewEvaluateArgs(PrepareEval(exp)))
+
+ if err != nil {
+ return runtime.RemoteObject{}, err
+ }
+
+ if res.ObjectID == nil {
+ return runtime.RemoteObject{}, errors.Wrap(core.ErrUnexpected, "unable to resolve remote object")
+ }
+
+ return res, nil
+}
+
+func (ec *ExecutionContext) ResolveNode(ctx context.Context, nodeID dom.NodeID) (runtime.RemoteObject, error) {
+ args := dom.NewResolveNodeArgs().SetNodeID(nodeID)
+
+ if ec.contextID != EmptyExecutionContextID {
+ args.SetExecutionContextID(ec.contextID)
+ }
+
+ repl, err := ec.client.DOM.ResolveNode(ctx, args)
+
+ if err != nil {
+ return runtime.RemoteObject{}, err
+ }
+
+ if repl.Object.ObjectID == nil {
+ return runtime.RemoteObject{}, errors.Wrap(core.ErrUnexpected, "unable to resolve remote object")
+ }
+
+ return repl.Object, nil
+}
+
+func (ec *ExecutionContext) evalWithArgumentsInternal(ctx context.Context, exp string, args []runtime.CallArgument, ret bool) (runtime.RemoteObject, error) {
+ cfArgs := runtime.
+ NewCallFunctionOnArgs(exp).
+ SetArguments(args).
+ SetReturnByValue(ret)
if ec.contextID != EmptyExecutionContextID {
cfArgs.SetExecutionContextID(ec.contextID)
@@ -239,10 +295,10 @@ func (ec *ExecutionContext) CallFunction(ctx context.Context, declaration string
return runtime.RemoteObject{}, err
}
- if repl.ExceptionDetails != nil {
- exception := *repl.ExceptionDetails
+ err = ec.handleException(repl.ExceptionDetails)
- return runtime.RemoteObject{}, errors.New(exception.Error())
+ if err != nil {
+ return runtime.RemoteObject{}, err
}
return repl.Result, nil
@@ -273,23 +329,28 @@ func (ec *ExecutionContext) evalInternal(ctx context.Context, args *runtime.Eval
return runtime.RemoteObject{}, err
}
- if out.ExceptionDetails != nil {
- ex := out.ExceptionDetails
- desc := *ex.Exception.Description
-
- var err error
-
- if strings.Contains(desc, drivers.ErrNotFound.Error()) {
- err = drivers.ErrNotFound
- } else {
- err = core.Error(
- core.ErrUnexpected,
- fmt.Sprintf("%s: %s", ex.Text, desc),
- )
- }
+ err = ec.handleException(out.ExceptionDetails)
+ if err != nil {
return runtime.RemoteObject{}, err
}
return out.Result, nil
}
+
+func (ec *ExecutionContext) handleException(details *runtime.ExceptionDetails) error {
+ if details == nil {
+ return nil
+ }
+
+ desc := *details.Exception.Description
+
+ if strings.Contains(desc, drivers.ErrNotFound.Error()) {
+ return drivers.ErrNotFound
+ }
+
+ return core.Error(
+ core.ErrUnexpected,
+ fmt.Sprintf("%s: %s", details.Text, desc),
+ )
+}
diff --git a/pkg/drivers/cdp/events/wait.go b/pkg/drivers/cdp/events/wait.go
index 0aaf5643..a3cf3da8 100644
--- a/pkg/drivers/cdp/events/wait.go
+++ b/pkg/drivers/cdp/events/wait.go
@@ -64,7 +64,7 @@ func NewEvalWaitTask(
) *WaitTask {
return NewWaitTask(
func(ctx context.Context) (core.Value, error) {
- return ec.EvalWithValue(
+ return ec.EvalWithReturnValue(
ctx,
predicate,
)
diff --git a/pkg/drivers/cdp/helpers.go b/pkg/drivers/cdp/helpers.go
index b359c8da..be6f9ead 100644
--- a/pkg/drivers/cdp/helpers.go
+++ b/pkg/drivers/cdp/helpers.go
@@ -93,7 +93,7 @@ func setInnerHTML(ctx context.Context, client *cdp.Client, exec *eval.ExecutionC
return err
}
- _, err = exec.CallFunction(ctx, templates.SetInnerHTML(),
+ err = exec.EvalWithArguments(ctx, templates.SetInnerHTML(),
runtime.CallArgument{
ObjectID: objID,
},
@@ -135,7 +135,7 @@ func getInnerHTML(ctx context.Context, client *cdp.Client, exec *eval.ExecutionC
return values.NewString(res.String()), nil
}
- repl, err := exec.EvalWithValue(ctx, "return document.documentElement.innerHTML")
+ repl, err := exec.EvalWithReturnValue(ctx, "return document.documentElement.innerHTML")
if err != nil {
return "", err
@@ -169,7 +169,7 @@ func setInnerText(ctx context.Context, client *cdp.Client, exec *eval.ExecutionC
return err
}
- _, err = exec.CallFunction(ctx, templates.SetInnerText(),
+ err = exec.EvalWithArguments(ctx, templates.SetInnerText(),
runtime.CallArgument{
ObjectID: objID,
},
@@ -211,7 +211,7 @@ func getInnerText(ctx context.Context, client *cdp.Client, exec *eval.ExecutionC
return values.NewString(res.String()), err
}
- repl, err := exec.EvalWithValue(ctx, "return document.documentElement.innerText")
+ repl, err := exec.EvalWithReturnValue(ctx, "return document.documentElement.innerText")
if err != nil {
return "", err
diff --git a/pkg/drivers/cdp/input/manager.go b/pkg/drivers/cdp/input/manager.go
index 310665a8..5c53ecd1 100644
--- a/pkg/drivers/cdp/input/manager.go
+++ b/pkg/drivers/cdp/input/manager.go
@@ -2,17 +2,16 @@ package input
import (
"context"
- "fmt"
"time"
- "github.com/gofrs/uuid"
"github.com/mafredri/cdp"
"github.com/mafredri/cdp/protocol/dom"
+ "github.com/mafredri/cdp/protocol/runtime"
"github.com/MontFerret/ferret/pkg/drivers/cdp/eval"
+ "github.com/MontFerret/ferret/pkg/drivers/cdp/templates"
"github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values"
- "github.com/MontFerret/ferret/pkg/runtime/values/types"
)
type Manager struct {
@@ -44,116 +43,67 @@ func (m *Manager) Mouse() *Mouse {
return m.mouse
}
-func (m *Manager) Scroll(ctx context.Context, x, y values.Float) error {
- return m.exec.Eval(ctx, fmt.Sprintf(`
- window.scrollBy({
- top: %s,
- left: %s,
- behavior: 'instant'
- });
- `,
- eval.ParamFloat(float64(x)),
- eval.ParamFloat(float64(y)),
- ))
-}
-
-func (m *Manager) ScrollIntoViewBySelector(ctx context.Context, selector values.String) error {
- return m.exec.Eval(ctx, fmt.Sprintf(`
- var el = document.querySelector(%s);
-
- if (el == null) {
- throw new Error("element not found");
- }
-
- el.scrollIntoView({
- behavior: 'instant'
- });
-
- return true;
- `, eval.ParamString(selector.String()),
- ))
-}
-
-func (m *Manager) ScrollIntoViewByNodeID(ctx context.Context, nodeID dom.NodeID) error {
- var attrID = "data-ferret-scroll"
-
- id, err := uuid.NewV4()
-
- if err != nil {
- return err
- }
-
- err = m.client.DOM.SetAttributeValue(ctx, dom.NewSetAttributeValueArgs(nodeID, attrID, id.String()))
-
- if err != nil {
- return err
- }
-
- err = m.exec.Eval(
- ctx,
- fmt.Sprintf(`
- var el = document.querySelector('[%s="%s"]');
- if (el == null) {
- throw new Error('element not found');
- }
-
- el.scrollIntoView({
- behavior: 'instant',
- inline: 'center',
- block: 'center'
- });
- `,
- attrID,
- id.String(),
- ))
-
- if err != nil {
- return err
- }
-
- err = m.client.DOM.RemoveAttribute(ctx, dom.NewRemoveAttributeArgs(nodeID, attrID))
-
- return err
-}
-
func (m *Manager) ScrollTop(ctx context.Context) error {
- return m.exec.Eval(ctx, `
- window.scrollTo({
- left: 0,
- top: 0,
- behavior: 'instant'
- });
- `)
+ return m.exec.Eval(ctx, templates.ScrollTop())
}
func (m *Manager) ScrollBottom(ctx context.Context) error {
- return m.exec.Eval(ctx, `
- window.scrollTo({
- left: 0,
- top: window.document.body.scrollHeight,
- behavior: 'instant'
- });
- `)
+ return m.exec.Eval(ctx, templates.ScrollBottom())
}
-func (m *Manager) MoveMouseBySelector(ctx context.Context, parentNodeID dom.NodeID, selector values.String) error {
+func (m *Manager) ScrollIntoView(ctx context.Context, objectID runtime.RemoteObjectID) error {
+ return m.exec.EvalWithArguments(
+ ctx,
+ templates.ScrollIntoView(),
+ runtime.CallArgument{
+ ObjectID: &objectID,
+ },
+ )
+}
+
+func (m *Manager) ScrollIntoViewBySelector(ctx context.Context, selector values.String) error {
+ return m.exec.Eval(ctx, templates.ScrollIntoViewBySelector(selector.String()))
+}
+
+func (m *Manager) ScrollByXY(ctx context.Context, x, y values.Float) error {
+ return m.exec.Eval(
+ ctx,
+ templates.Scroll(eval.ParamFloat(float64(x)), eval.ParamFloat(float64(y))),
+ )
+}
+
+func (m *Manager) Focus(ctx context.Context, objectID runtime.RemoteObjectID) error {
+ err := m.ScrollIntoView(ctx, objectID)
+
+ if err != nil {
+ return err
+ }
+
+ return m.client.DOM.Focus(ctx, dom.NewFocusArgs().SetObjectID(objectID))
+}
+
+func (m *Manager) FocusBySelector(ctx context.Context, parentNodeID dom.NodeID, selector values.String) error {
+ err := m.ScrollIntoViewBySelector(ctx, selector)
+
+ if err != nil {
+ return err
+ }
+
found, err := m.client.DOM.QuerySelector(ctx, dom.NewQuerySelectorArgs(parentNodeID, selector.String()))
if err != nil {
- return err
+ return nil
}
- return m.MoveMouseByNodeID(ctx, found.NodeID)
+ return m.client.DOM.Focus(ctx, dom.NewFocusArgs().SetNodeID(found.NodeID))
}
-func (m *Manager) MoveMouseByNodeID(ctx context.Context, nodeID dom.NodeID) error {
- err := m.ScrollIntoViewByNodeID(ctx, nodeID)
-
- if err != nil {
+func (m *Manager) MoveMouse(ctx context.Context, objectID runtime.RemoteObjectID) error {
+ if err := m.ScrollIntoView(ctx, objectID); err != nil {
return err
}
- q, err := GetClickablePointByNodeID(ctx, m.client, nodeID)
+ q, err := GetClickablePointByObjectID(ctx, m.client, objectID)
if err != nil {
return err
@@ -162,26 +112,40 @@ func (m *Manager) MoveMouseByNodeID(ctx context.Context, nodeID dom.NodeID) erro
return m.mouse.Move(ctx, q.X, q.Y)
}
-func (m *Manager) MoveMouse(ctx context.Context, x, y values.Float) error {
- return m.mouse.Move(ctx, float64(x), float64(y))
-}
+func (m *Manager) MoveMouseBySelector(ctx context.Context, parentNodeID dom.NodeID, selector values.String) error {
+ if err := m.ScrollIntoViewBySelector(ctx, selector); err != nil {
+ return err
+ }
-func (m *Manager) ClickBySelector(ctx context.Context, parentNodeID dom.NodeID, selector values.String) error {
found, err := m.client.DOM.QuerySelector(ctx, dom.NewQuerySelectorArgs(parentNodeID, selector.String()))
if err != nil {
return err
}
- return m.ClickByNodeID(ctx, found.NodeID)
-}
+ q, err := GetClickablePointByNodeID(ctx, m.client, found.NodeID)
-func (m *Manager) ClickByNodeID(ctx context.Context, nodeID dom.NodeID) error {
- if err := m.ScrollIntoViewByNodeID(ctx, nodeID); err != nil {
+ if err != nil {
return err
}
- points, err := GetClickablePointByNodeID(ctx, m.client, nodeID)
+ return m.mouse.Move(ctx, q.X, q.Y)
+}
+
+func (m *Manager) MoveMouseByXY(ctx context.Context, x, y values.Float) error {
+ if err := m.ScrollByXY(ctx, x, y); err != nil {
+ return err
+ }
+
+ return m.mouse.Move(ctx, float64(x), float64(y))
+}
+
+func (m *Manager) Click(ctx context.Context, objectID runtime.RemoteObjectID) error {
+ if err := m.ScrollIntoView(ctx, objectID); err != nil {
+ return err
+ }
+
+ points, err := GetClickablePointByObjectID(ctx, m.client, objectID)
if err != nil {
return err
@@ -194,22 +158,71 @@ func (m *Manager) ClickByNodeID(ctx context.Context, nodeID dom.NodeID) error {
return nil
}
-func (m *Manager) TypeBySelector(ctx context.Context, parentNodeID dom.NodeID, selector values.String, text core.Value, delay values.Int) error {
+func (m *Manager) ClickBySelector(ctx context.Context, parentNodeID dom.NodeID, selector values.String) error {
+ if err := m.ScrollIntoViewBySelector(ctx, selector); err != nil {
+ return err
+ }
+
found, err := m.client.DOM.QuerySelector(ctx, dom.NewQuerySelectorArgs(parentNodeID, selector.String()))
if err != nil {
return err
}
- return m.TypeByNodeID(ctx, found.NodeID, text, delay)
-}
+ points, err := GetClickablePointByNodeID(ctx, m.client, found.NodeID)
-func (m *Manager) TypeByNodeID(ctx context.Context, nodeID dom.NodeID, text core.Value, delay values.Int) error {
- if err := m.ScrollIntoViewByNodeID(ctx, nodeID); err != nil {
+ if err != nil {
return err
}
- if err := m.client.DOM.Focus(ctx, dom.NewFocusArgs().SetNodeID(nodeID)); err != nil {
+ if err := m.mouse.Click(ctx, points.X, points.Y, 50); err != nil {
+ return nil
+ }
+
+ return nil
+}
+
+func (m *Manager) ClickBySelectorAll(ctx context.Context, parentNodeID dom.NodeID, selector values.String) error {
+ if err := m.ScrollIntoViewBySelector(ctx, selector); err != nil {
+ return err
+ }
+
+ found, err := m.client.DOM.QuerySelectorAll(ctx, dom.NewQuerySelectorAllArgs(parentNodeID, selector.String()))
+
+ if err != nil {
+ return err
+ }
+
+ for _, nodeID := range found.NodeIDs {
+ _, min := core.NumberBoundaries(100)
+ beforeTypeDelay := time.Duration(min)
+
+ time.Sleep(beforeTypeDelay * time.Millisecond)
+
+ points, err := GetClickablePointByNodeID(ctx, m.client, nodeID)
+
+ if err != nil {
+ return err
+ }
+
+ if err := m.mouse.Click(ctx, points.X, points.Y, 50); err != nil {
+ return nil
+ }
+ }
+
+ return nil
+}
+
+func (m *Manager) Type(ctx context.Context, objectID runtime.RemoteObjectID, text core.Value, delay values.Int) error {
+ err := m.ScrollIntoView(ctx, objectID)
+
+ if err != nil {
+ return err
+ }
+
+ err = m.client.DOM.Focus(ctx, dom.NewFocusArgs().SetObjectID(objectID))
+
+ if err != nil {
return err
}
@@ -221,85 +234,71 @@ func (m *Manager) TypeByNodeID(ctx context.Context, nodeID dom.NodeID, text core
return m.keyboard.Type(ctx, text.String(), int(delay))
}
-func (m *Manager) SelectBySelector(ctx context.Context, parentNodeID dom.NodeID, selector values.String, value *values.Array) (*values.Array, error) {
+func (m *Manager) TypeBySelector(ctx context.Context, parentNodeID dom.NodeID, selector values.String, text core.Value, delay values.Int) error {
+ err := m.ScrollIntoViewBySelector(ctx, selector)
+
+ if err != nil {
+ return err
+ }
+
found, err := m.client.DOM.QuerySelector(ctx, dom.NewQuerySelectorArgs(parentNodeID, selector.String()))
if err != nil {
- return nil, err
+ return err
}
- return m.SelectByNodeID(ctx, found.NodeID, value)
+ err = m.client.DOM.Focus(ctx, dom.NewFocusArgs().SetNodeID(found.NodeID))
+
+ if err != nil {
+ return err
+ }
+
+ _, min := core.NumberBoundaries(float64(delay))
+ beforeTypeDelay := time.Duration(min)
+
+ time.Sleep(beforeTypeDelay * time.Millisecond)
+
+ return m.keyboard.Type(ctx, text.String(), int(delay))
}
-func (m *Manager) SelectByNodeID(ctx context.Context, nodeID dom.NodeID, value *values.Array) (*values.Array, error) {
- if err := m.ScrollIntoViewByNodeID(ctx, nodeID); err != nil {
- return nil, err
+func (m *Manager) Select(ctx context.Context, objectID runtime.RemoteObjectID, value *values.Array) (*values.Array, error) {
+ if err := m.Focus(ctx, objectID); err != nil {
+ return values.NewArray(0), err
}
- if err := m.client.DOM.Focus(ctx, dom.NewFocusArgs().SetNodeID(nodeID)); err != nil {
- return nil, err
- }
-
- var attrID = "data-ferret-select"
-
- id, err := uuid.NewV4()
+ val, err := m.exec.EvalWithArgumentsAndReturnValue(ctx, templates.Select(value.String()), runtime.CallArgument{
+ ObjectID: &objectID,
+ })
if err != nil {
return nil, err
}
- err = m.client.DOM.SetAttributeValue(ctx, dom.NewSetAttributeValueArgs(nodeID, attrID, id.String()))
+ arr, ok := val.(*values.Array)
- if err != nil {
- return nil, err
+ if !ok {
+ return values.NewArray(0), core.ErrUnexpected
}
- res, err := m.exec.EvalWithValue(
- ctx,
- fmt.Sprintf(`
- var el = document.querySelector('[%s="%s"]');
- if (el == null) {
- return [];
- }
- var values = %s;
- if (el.nodeName.toLowerCase() !== 'select') {
- throw new Error('element is not a