mirror of
https://github.com/MontFerret/ferret.git
synced 2025-11-06 08:39:09 +02:00
Adds function to type value into input (#81)
* adds function to type input * changes per feedback * more PR feedback changes * add context.Background()
This commit is contained in:
@@ -3,6 +3,10 @@ package dynamic
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"hash/fnv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/MontFerret/ferret/pkg/html/dynamic/eval"
|
||||
"github.com/MontFerret/ferret/pkg/html/dynamic/events"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
@@ -10,13 +14,11 @@ import (
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/mafredri/cdp"
|
||||
"github.com/mafredri/cdp/protocol/dom"
|
||||
"github.com/mafredri/cdp/protocol/input"
|
||||
"github.com/mafredri/cdp/protocol/page"
|
||||
"github.com/mafredri/cdp/rpcc"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/rs/zerolog"
|
||||
"hash/fnv"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
const BlankPageURL = "about:blank"
|
||||
@@ -416,27 +418,21 @@ func (doc *HTMLDocument) ClickBySelectorAll(selector values.String) (values.Bool
|
||||
return values.False, nil
|
||||
}
|
||||
|
||||
func (doc *HTMLDocument) InputBySelector(selector values.String, value core.Value) (values.Boolean, error) {
|
||||
func (doc *HTMLDocument) InputBySelector(selector values.String, value core.Value, delay values.Int) (values.Boolean, error) {
|
||||
ctx := context.Background()
|
||||
|
||||
valStr := value.String()
|
||||
|
||||
res, err := eval.Eval(
|
||||
doc.client,
|
||||
fmt.Sprintf(
|
||||
`
|
||||
fmt.Sprintf(`
|
||||
var el = document.querySelector(%s);
|
||||
|
||||
if (el == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var evt = new window.Event('input', { bubbles: true });
|
||||
|
||||
el.value = %s
|
||||
el.dispatchEvent(evt);
|
||||
|
||||
el.focus();
|
||||
return true;
|
||||
`,
|
||||
eval.ParamString(selector.String()),
|
||||
eval.ParamString(value.String()),
|
||||
),
|
||||
`, eval.ParamString(selector.String())),
|
||||
true,
|
||||
false,
|
||||
)
|
||||
@@ -445,11 +441,25 @@ func (doc *HTMLDocument) InputBySelector(selector values.String, value core.Valu
|
||||
return values.False, err
|
||||
}
|
||||
|
||||
if res.Type() == core.BooleanType {
|
||||
return res.(values.Boolean), nil
|
||||
if res.Type() == core.BooleanType && res.(values.Boolean) == values.False {
|
||||
return values.False, nil
|
||||
}
|
||||
|
||||
return values.False, nil
|
||||
delayMs := time.Duration(delay)
|
||||
|
||||
time.Sleep(delayMs * time.Millisecond)
|
||||
|
||||
for _, ch := range valStr {
|
||||
for _, ev := range []string{"keyDown", "keyUp"} {
|
||||
ke := input.NewDispatchKeyEventArgs(ev).SetText(string(ch))
|
||||
if err := doc.client.Input.DispatchKeyEvent(ctx, ke); err != nil {
|
||||
return values.False, err
|
||||
}
|
||||
time.Sleep(delayMs * time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
return values.True, nil
|
||||
}
|
||||
|
||||
func (doc *HTMLDocument) WaitForSelector(selector values.String, timeout values.Int) error {
|
||||
|
||||
@@ -3,6 +3,12 @@ package dynamic
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"hash/fnv"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/MontFerret/ferret/pkg/html/common"
|
||||
"github.com/MontFerret/ferret/pkg/html/dynamic/eval"
|
||||
"github.com/MontFerret/ferret/pkg/html/dynamic/events"
|
||||
@@ -10,12 +16,8 @@ import (
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/mafredri/cdp"
|
||||
"github.com/mafredri/cdp/protocol/dom"
|
||||
"github.com/mafredri/cdp/protocol/input"
|
||||
"github.com/rs/zerolog"
|
||||
"hash/fnv"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
const DefaultTimeout = time.Second * 30
|
||||
@@ -586,11 +588,31 @@ func (el *HTMLElement) Click() (values.Boolean, error) {
|
||||
return events.DispatchEvent(ctx, el.client, el.id, "click")
|
||||
}
|
||||
|
||||
func (el *HTMLElement) Input(value core.Value) error {
|
||||
func (el *HTMLElement) Input(value core.Value, delay values.Int) error {
|
||||
ctx, cancel := contextWithTimeout()
|
||||
defer cancel()
|
||||
|
||||
return el.client.DOM.SetAttributeValue(ctx, dom.NewSetAttributeValueArgs(el.id, "value", value.String()))
|
||||
if err := el.client.DOM.Focus(ctx, dom.NewFocusArgs().SetNodeID(el.id)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
delayMs := time.Duration(delay)
|
||||
|
||||
time.Sleep(delayMs * time.Millisecond)
|
||||
|
||||
valStr := value.String()
|
||||
|
||||
for _, ch := range valStr {
|
||||
for _, ev := range []string{"keyDown", "keyUp"} {
|
||||
ke := input.NewDispatchKeyEventArgs(ev).SetText(string(ch))
|
||||
if err := el.client.Input.DispatchKeyEvent(ctx, ke); err != nil {
|
||||
return err
|
||||
}
|
||||
time.Sleep(delayMs * time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (el *HTMLElement) IsConnected() values.Boolean {
|
||||
|
||||
@@ -2,71 +2,92 @@ package html
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/MontFerret/ferret/pkg/html/dynamic"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
)
|
||||
|
||||
/*
|
||||
* Sends a value to an underlying input element.
|
||||
* Types a value to an underlying input element.
|
||||
* @param source (Document | Element) - Event target.
|
||||
* @param valueOrSelector (String) - Selector or a value.
|
||||
* @param value (String) - Target value.
|
||||
* @param delay (Int, optional) - Waits delay milliseconds between keystrokes
|
||||
* @returns (Boolean) - Returns true if an element was found.
|
||||
*/
|
||||
func Input(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
err := core.ValidateArgs(args, 2, 3)
|
||||
err := core.ValidateArgs(args, 2, 4)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
// TYPE(el, "foobar")
|
||||
if len(args) == 2 {
|
||||
arg1 := args[0]
|
||||
arg1 := args[0]
|
||||
err = core.ValidateType(arg1, core.HTMLDocumentType, core.HTMLElementType)
|
||||
|
||||
err := core.ValidateType(arg1, core.HTMLElementType)
|
||||
if err != nil {
|
||||
return values.False, err
|
||||
}
|
||||
|
||||
switch args[0].(type) {
|
||||
case *dynamic.HTMLDocument:
|
||||
|
||||
doc, ok := arg1.(*dynamic.HTMLDocument)
|
||||
|
||||
if !ok {
|
||||
return values.False, core.Errors(core.ErrInvalidType, ErrNotDynamic)
|
||||
}
|
||||
|
||||
// selector
|
||||
arg2 := args[1]
|
||||
err = core.ValidateType(arg2, core.StringType)
|
||||
|
||||
if err != nil {
|
||||
return values.False, err
|
||||
}
|
||||
|
||||
delay := values.Int(0)
|
||||
if len(args) == 4 {
|
||||
arg4 := args[3]
|
||||
|
||||
err = core.ValidateType(arg4, core.IntType)
|
||||
if err != nil {
|
||||
return values.False, err
|
||||
}
|
||||
|
||||
delay = arg4.(values.Int)
|
||||
}
|
||||
|
||||
return doc.InputBySelector(arg2.(values.String), args[2], delay)
|
||||
|
||||
case *dynamic.HTMLElement:
|
||||
el, ok := arg1.(*dynamic.HTMLElement)
|
||||
|
||||
if !ok {
|
||||
return values.False, core.Errors(core.ErrInvalidType, ErrNotDynamic)
|
||||
}
|
||||
|
||||
err = el.Input(args[1])
|
||||
delay := values.Int(0)
|
||||
if len(args) == 3 {
|
||||
arg3 := args[2]
|
||||
|
||||
err = core.ValidateType(arg3, core.IntType)
|
||||
if err != nil {
|
||||
return values.False, err
|
||||
}
|
||||
|
||||
delay = arg3.(values.Int)
|
||||
}
|
||||
|
||||
err = el.Input(args[1], delay)
|
||||
|
||||
if err != nil {
|
||||
return values.False, err
|
||||
}
|
||||
|
||||
return values.True, nil
|
||||
default:
|
||||
return values.False, core.Errors(core.ErrInvalidArgument)
|
||||
}
|
||||
|
||||
arg1 := args[0]
|
||||
|
||||
err = core.ValidateType(arg1, core.HTMLDocumentType)
|
||||
|
||||
if err != nil {
|
||||
return values.False, err
|
||||
}
|
||||
|
||||
arg2 := args[1]
|
||||
|
||||
err = core.ValidateType(arg2, core.StringType)
|
||||
|
||||
if err != nil {
|
||||
return values.False, err
|
||||
}
|
||||
|
||||
doc, ok := arg1.(*dynamic.HTMLDocument)
|
||||
|
||||
if !ok {
|
||||
return values.False, core.Errors(core.ErrInvalidType, ErrNotDynamic)
|
||||
}
|
||||
|
||||
return doc.InputBySelector(arg2.(values.String), args[2])
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user