mirror of
https://github.com/MontFerret/ferret.git
synced 2025-03-03 15:02:32 +02:00
Merge branch 'master' of https://github.com/MontFerret/ferret
This commit is contained in:
commit
e61ea0e4e0
@ -1,5 +1,9 @@
|
||||
## Changelog
|
||||
|
||||
### 0.8.3
|
||||
#### Fixed
|
||||
- Unable to click by selector using an element.
|
||||
|
||||
### 0.8.2
|
||||
#### Fixed
|
||||
- Scrolling position is not centered. [#343](https://github.com/MontFerret/ferret/pull/343)
|
||||
|
@ -55,7 +55,7 @@ export default class AppearableComponent extends React.PureComponent {
|
||||
render() {
|
||||
const btnId = `${this.props.id}-btn`;
|
||||
|
||||
return e("div", {className: "card"}, [
|
||||
return e("div", { id: this.props.id, className: "card"}, [
|
||||
e("div", { className: "card-header"}, [
|
||||
e("button", {
|
||||
id: btnId,
|
||||
|
@ -34,7 +34,7 @@ export default class ClickableComponent extends React.PureComponent {
|
||||
classNames.push("alert-success");
|
||||
}
|
||||
|
||||
return e("div", {className: "card clickable"}, [
|
||||
return e("div", { id: this.props.id, className: "card clickable"}, [
|
||||
e("div", { className: "card-header"}, [
|
||||
e("button", {
|
||||
id: btnId,
|
||||
|
@ -42,7 +42,7 @@ export default class FocusableComponent extends React.PureComponent {
|
||||
classNames.push("alert-success");
|
||||
}
|
||||
|
||||
return e("div", {className: "card focusable"}, [
|
||||
return e("div", {id: this.props.id, className: "card focusable"}, [
|
||||
e("div", { className: "card-header"}, [
|
||||
e("div", { classNames: "form-group" }, [
|
||||
e("input", {
|
||||
|
@ -30,7 +30,7 @@ export default class HoverableComponent extends React.PureComponent {
|
||||
]);
|
||||
}
|
||||
|
||||
return e("div", { className: "card"}, [
|
||||
return e("div", { id: this.props.id, className: "card"}, [
|
||||
e("div", {className: "card-header"}, [
|
||||
e("button", {
|
||||
id: "hoverable-btn",
|
||||
|
@ -9,16 +9,16 @@ export default class EventsPage extends React.Component {
|
||||
render() {
|
||||
return e("div", { id: "page-events" }, [
|
||||
e("div", { className: "row" }, [
|
||||
e("div", { className: "col-lg-4"}, [
|
||||
e("div", { className: "col-lg-4" }, [
|
||||
e(Hoverable),
|
||||
]),
|
||||
e("div", { className: "col-lg-4"}, [
|
||||
e("div", { className: "col-lg-4" }, [
|
||||
e(Clickable, {
|
||||
id: "wait-class",
|
||||
title: "Add class"
|
||||
})
|
||||
]),
|
||||
e("div", { className: "col-lg-4"}, [
|
||||
e("div", { className: "col-lg-4" }, [
|
||||
e(Clickable, {
|
||||
id: "wait-class-random",
|
||||
title: "Add class 2",
|
||||
@ -27,14 +27,14 @@ export default class EventsPage extends React.Component {
|
||||
])
|
||||
]),
|
||||
e("div", { className: "row" }, [
|
||||
e("div", { className: "col-lg-4"}, [
|
||||
e("div", { className: "col-lg-4" }, [
|
||||
e(Clickable, {
|
||||
id: "wait-no-class",
|
||||
title: "Remove class",
|
||||
show: true
|
||||
})
|
||||
]),
|
||||
e("div", { className: "col-lg-4"}, [
|
||||
e("div", { className: "col-lg-4" }, [
|
||||
e(Clickable, {
|
||||
id: "wait-no-class-random",
|
||||
title: "Remove class 2",
|
||||
@ -42,7 +42,7 @@ export default class EventsPage extends React.Component {
|
||||
randomTimeout: true
|
||||
})
|
||||
]),
|
||||
e("div", { className: "col-lg-4"}, [
|
||||
e("div", { className: "col-lg-4" }, [
|
||||
e(Appearable, {
|
||||
id: "wait-element",
|
||||
appear: true,
|
||||
@ -51,14 +51,14 @@ export default class EventsPage extends React.Component {
|
||||
]),
|
||||
]),
|
||||
e("div", { className: "row" }, [
|
||||
e("div", { className: "col-lg-4"}, [
|
||||
e("div", { className: "col-lg-4" }, [
|
||||
e(Appearable, {
|
||||
id: "wait-no-element",
|
||||
appear: false,
|
||||
title: "Disappearable"
|
||||
})
|
||||
]),
|
||||
e("div", { className: "col-lg-4"}, [
|
||||
e("div", { className: "col-lg-4" }, [
|
||||
e(Appearable, {
|
||||
id: "wait-style",
|
||||
appear: true,
|
||||
@ -66,7 +66,7 @@ export default class EventsPage extends React.Component {
|
||||
useStyle: true,
|
||||
})
|
||||
]),
|
||||
e("div", { className: "col-lg-4"}, [
|
||||
e("div", { className: "col-lg-4" }, [
|
||||
e(Appearable, {
|
||||
id: "wait-no-style",
|
||||
appear: false,
|
||||
@ -76,7 +76,7 @@ export default class EventsPage extends React.Component {
|
||||
]),
|
||||
]),
|
||||
e("div", { className: "row" }, [
|
||||
e("div", { className: "col-lg-4"}, [
|
||||
e("div", { className: "col-lg-4" }, [
|
||||
e(Focusable, {
|
||||
id: "focus",
|
||||
appear: false,
|
||||
|
@ -1,4 +1,4 @@
|
||||
export default function random(min = 1000, max = 5000) {
|
||||
export default function random(min = 1000, max = 4000) {
|
||||
const val = Math.random() * 1000 * 10;
|
||||
|
||||
if (val < min) {
|
||||
|
10
e2e/tests/dynamic/element/click/click.fql
Normal file
10
e2e/tests/dynamic/element/click/click.fql
Normal file
@ -0,0 +1,10 @@
|
||||
LET url = @dynamic + "/#/events"
|
||||
LET page = DOCUMENT(url, true)
|
||||
|
||||
LET btn = ELEMENT(page, "#wait-class-random-btn")
|
||||
|
||||
CLICK(btn)
|
||||
|
||||
WAIT_CLASS(page, "#wait-class-random-content", "alert-success")
|
||||
|
||||
RETURN ""
|
10
e2e/tests/dynamic/element/click/click_by_selector.fql
Normal file
10
e2e/tests/dynamic/element/click/click_by_selector.fql
Normal file
@ -0,0 +1,10 @@
|
||||
LET url = "http://192.168.1.170:8080/#/events"
|
||||
LET page = DOCUMENT(url, true)
|
||||
|
||||
LET div = ELEMENT(page, "#wait-class-random")
|
||||
|
||||
CLICK(div, "button")
|
||||
|
||||
WAIT_CLASS(page, "#wait-class-random-content", "alert-success", 10000)
|
||||
|
||||
RETURN ""
|
@ -1,9 +1,10 @@
|
||||
LET doc = DOCUMENT("https://github.com/", { driver: "cdp" })
|
||||
LET btn = ELEMENT(doc, ".HeaderMenu a")
|
||||
|
||||
CLICK(btn)
|
||||
HOVER(doc, ".HeaderMenu-details")
|
||||
CLICK(doc, ".HeaderMenu a")
|
||||
|
||||
WAIT_NAVIGATION(doc)
|
||||
WAIT_ELEMENT(doc, '.IconNav')
|
||||
|
||||
FOR el IN ELEMENTS(doc, '.IconNav a')
|
||||
RETURN TRIM(el.innerText)
|
||||
RETURN TRIM(el.innerText)
|
||||
|
@ -1,16 +1,20 @@
|
||||
LET google = DOCUMENT("https://www.google.com/", { driver: "cdp" })
|
||||
LET google = DOCUMENT("https://www.google.com/", {
|
||||
driver: "cdp",
|
||||
userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.87 Safari/537.36"
|
||||
})
|
||||
|
||||
INPUT(google, 'input[name="q"]', "ferret", 25)
|
||||
HOVER(google, 'input[name="q"]')
|
||||
WAIT(RAND(100))
|
||||
INPUT(google, 'input[name="q"]', @criteria, 30)
|
||||
|
||||
WAIT(RAND(100))
|
||||
|
||||
WAIT_ELEMENT(google, '.UUbT9')
|
||||
WAIT(RAND(100))
|
||||
CLICK(google, 'input[name="btnK"]')
|
||||
|
||||
WAIT_NAVIGATION(google)
|
||||
WAIT_ELEMENT(google, '.g', 5000)
|
||||
|
||||
FOR result IN ELEMENTS(google, '.g')
|
||||
// filter out extra elements like videos and 'People also ask'
|
||||
FILTER TRIM(result.attributes.class) == 'g'
|
||||
RETURN {
|
||||
title: INNER_TEXT(result, 'h3'),
|
||||
description: INNER_TEXT(result, '.st'),
|
||||
url: INNER_TEXT(result, 'cite')
|
||||
}
|
@ -318,11 +318,11 @@ func (doc *HTMLDocument) GetURL() values.String {
|
||||
}
|
||||
|
||||
func (doc *HTMLDocument) ClickBySelector(ctx context.Context, selector values.String) error {
|
||||
return doc.input.ClickBySelector(ctx, doc.element.id.nodeID, selector)
|
||||
return doc.element.ClickBySelector(ctx, selector)
|
||||
}
|
||||
|
||||
func (doc *HTMLDocument) ClickBySelectorAll(ctx context.Context, selector values.String) error {
|
||||
return doc.input.ClickBySelectorAll(ctx, doc.element.id.nodeID, selector)
|
||||
return doc.element.ClickBySelectorAll(ctx, selector)
|
||||
}
|
||||
|
||||
func (doc *HTMLDocument) InputBySelector(ctx context.Context, selector values.String, value core.Value, delay values.Int) error {
|
||||
|
@ -1055,6 +1055,14 @@ func (el *HTMLElement) Click(ctx context.Context) error {
|
||||
return el.input.Click(ctx, el.id.objectID)
|
||||
}
|
||||
|
||||
func (el *HTMLElement) ClickBySelector(ctx context.Context, selector values.String) error {
|
||||
return el.input.ClickBySelector(ctx, el.id.nodeID, selector)
|
||||
}
|
||||
|
||||
func (el *HTMLElement) ClickBySelectorAll(ctx context.Context, selector values.String) error {
|
||||
return el.input.ClickBySelectorAll(ctx, el.id.nodeID, selector)
|
||||
}
|
||||
|
||||
func (el *HTMLElement) Input(ctx context.Context, value core.Value, delay values.Int) error {
|
||||
if el.GetNodeName() != "INPUT" {
|
||||
return core.Error(core.ErrInvalidOperation, "element is not an <input> element.")
|
||||
|
@ -195,10 +195,14 @@ func LoadHTMLPage(
|
||||
repl, err := client.Page.Navigate(ctx, page.NewNavigateArgs(params.URL))
|
||||
|
||||
if err != nil {
|
||||
handleLoadError(logger, client)
|
||||
|
||||
return nil, errors.Wrap(err, "failed to load the page")
|
||||
}
|
||||
|
||||
if repl.ErrorText != nil {
|
||||
handleLoadError(logger, client)
|
||||
|
||||
return nil, errors.Wrapf(errors.New(*repl.ErrorText), "failed to load the page: %s", params.URL)
|
||||
}
|
||||
|
||||
|
@ -493,6 +493,14 @@ func (el *HTMLElement) Click(_ context.Context) error {
|
||||
return core.ErrNotSupported
|
||||
}
|
||||
|
||||
func (el *HTMLElement) ClickBySelector(_ context.Context, _ values.String) error {
|
||||
return core.ErrNotSupported
|
||||
}
|
||||
|
||||
func (el *HTMLElement) ClickBySelectorAll(_ context.Context, _ values.String) error {
|
||||
return core.ErrNotSupported
|
||||
}
|
||||
|
||||
func (el *HTMLElement) Input(_ context.Context, _ core.Value, _ values.Int) error {
|
||||
return core.ErrNotSupported
|
||||
}
|
||||
|
@ -43,6 +43,10 @@ type (
|
||||
ExistsBySelector(ctx context.Context, selector values.String) (values.Boolean, error)
|
||||
|
||||
XPath(ctx context.Context, expression values.String) (core.Value, error)
|
||||
|
||||
ClickBySelector(ctx context.Context, selector values.String) error
|
||||
|
||||
ClickBySelectorAll(ctx context.Context, selector values.String) error
|
||||
}
|
||||
|
||||
// HTMLElement is the most general base interface which most objects in a GetMainFrame implement.
|
||||
@ -127,10 +131,6 @@ type (
|
||||
|
||||
GetChildDocuments(ctx context.Context) (*values.Array, error)
|
||||
|
||||
ClickBySelector(ctx context.Context, selector values.String) error
|
||||
|
||||
ClickBySelectorAll(ctx context.Context, selector values.String) error
|
||||
|
||||
InputBySelector(ctx context.Context, selector values.String, value core.Value, delay values.Int) error
|
||||
|
||||
SelectBySelector(ctx context.Context, selector values.String, value *values.Array) (*values.Array, error)
|
||||
|
@ -1,6 +1,7 @@
|
||||
package values
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"hash/fnv"
|
||||
@ -258,3 +259,29 @@ func (t *Array) SortWith(sorter ArraySorter) *Array {
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func (t *Array) GetIn(ctx context.Context, path []core.Value) (core.Value, error) {
|
||||
if len(path) == 0 {
|
||||
return None, nil
|
||||
}
|
||||
|
||||
if typ := path[0].Type(); typ != types.Int {
|
||||
return None, core.TypeError(typ, types.Int)
|
||||
}
|
||||
|
||||
first := t.Get(path[0].(Int))
|
||||
|
||||
if len(path) == 1 {
|
||||
return first, nil
|
||||
}
|
||||
|
||||
getter, ok := first.(core.Getter)
|
||||
if !ok {
|
||||
return None, core.TypeError(
|
||||
first.Type(),
|
||||
core.NewType("Getter"),
|
||||
)
|
||||
}
|
||||
|
||||
return getter.GetIn(ctx, path[1:])
|
||||
}
|
||||
|
@ -1,12 +1,14 @@
|
||||
package values_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values/types"
|
||||
"testing"
|
||||
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values/types"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
@ -561,4 +563,90 @@ func TestArray(t *testing.T) {
|
||||
So(nestedInArr.Compare(nestedInClone), ShouldNotEqual, 0)
|
||||
})
|
||||
})
|
||||
|
||||
Convey(".GetIn", t, func() {
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
Convey("Should return the same as .Get when input is correct", func() {
|
||||
|
||||
Convey("Should return item by key", func() {
|
||||
key := values.NewInt(0)
|
||||
arr := values.NewArrayWith(
|
||||
values.NewInt(0),
|
||||
)
|
||||
|
||||
el, err := arr.GetIn(ctx, []core.Value{key})
|
||||
elGet := arr.Get(key)
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(el.Compare(elGet), ShouldEqual, 0)
|
||||
})
|
||||
|
||||
Convey("Should return None when no items", func() {
|
||||
key := values.NewInt(0)
|
||||
arr := values.NewArray(0)
|
||||
|
||||
el, err := arr.GetIn(ctx, []core.Value{key})
|
||||
elGet := arr.Get(key)
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(el.Compare(elGet), ShouldEqual, 0)
|
||||
})
|
||||
})
|
||||
|
||||
Convey("Should error when input is not correct", func() {
|
||||
|
||||
Convey("Should error when path[0] is not an int", func() {
|
||||
arr := values.NewArray(0)
|
||||
path := []core.Value{values.NewString("")}
|
||||
|
||||
el, err := arr.GetIn(ctx, path)
|
||||
|
||||
So(err, ShouldBeError)
|
||||
So(el.Compare(values.None), ShouldEqual, 0)
|
||||
})
|
||||
|
||||
Convey("Should error when first received item is not a Getter and len(path) > 1", func() {
|
||||
key := values.NewInt(0)
|
||||
arr := values.NewArrayWith(
|
||||
values.NewInt(1),
|
||||
)
|
||||
path := []core.Value{key, key}
|
||||
|
||||
el, err := arr.GetIn(ctx, path)
|
||||
|
||||
So(err, ShouldBeError)
|
||||
So(el.Compare(values.None), ShouldEqual, 0)
|
||||
})
|
||||
})
|
||||
|
||||
Convey("Should return None when len(path) == 0", func() {
|
||||
arr := values.NewArrayWith(
|
||||
values.NewInt(1),
|
||||
)
|
||||
|
||||
el, err := arr.GetIn(ctx, nil)
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(el.Compare(values.None), ShouldEqual, 0)
|
||||
})
|
||||
|
||||
Convey("Should call the nested Getter", func() {
|
||||
key := values.NewInt(0)
|
||||
arr := values.NewArrayWith(
|
||||
values.NewObjectWith(
|
||||
values.NewObjectProperty("foo", key),
|
||||
),
|
||||
)
|
||||
|
||||
el, err := arr.GetIn(ctx, []core.Value{
|
||||
key, // obj[0]
|
||||
values.NewString("foo"), // obj[0].foo
|
||||
})
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(el.Compare(key), ShouldEqual, 0)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -14,46 +14,18 @@ import (
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values/types"
|
||||
)
|
||||
|
||||
// GetIn checks that from implements core.Getter interface. If it implements,
|
||||
// GetIn call from.GetIn method, otherwise return error.
|
||||
func GetIn(ctx context.Context, from core.Value, byPath []core.Value) (core.Value, error) {
|
||||
if len(byPath) == 0 {
|
||||
return None, nil
|
||||
getter, ok := from.(core.Getter)
|
||||
if !ok {
|
||||
return None, core.TypeError(
|
||||
from.Type(),
|
||||
core.NewType("Getter"),
|
||||
)
|
||||
}
|
||||
|
||||
var result = from
|
||||
|
||||
for i, segment := range byPath {
|
||||
if result == None || result == nil {
|
||||
break
|
||||
}
|
||||
|
||||
segType := segment.Type()
|
||||
|
||||
switch segVal := result.(type) {
|
||||
case *Object:
|
||||
if segType != types.String {
|
||||
return nil, core.TypeError(segType, types.String)
|
||||
}
|
||||
|
||||
result, _ = segVal.Get(segment.(String))
|
||||
case *Array:
|
||||
if segType != types.Int {
|
||||
return nil, core.TypeError(segType, types.Int)
|
||||
}
|
||||
|
||||
result = segVal.Get(segment.(Int))
|
||||
case core.Getter:
|
||||
return segVal.GetIn(ctx, byPath[i:])
|
||||
default:
|
||||
return None, core.TypeError(
|
||||
from.Type(),
|
||||
types.Array,
|
||||
types.Object,
|
||||
core.NewType("Getter"),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
return getter.GetIn(ctx, byPath)
|
||||
}
|
||||
|
||||
func SetIn(ctx context.Context, to core.Value, byPath []core.Value, value core.Value) error {
|
||||
|
@ -1,6 +1,7 @@
|
||||
package values
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"hash/fnv"
|
||||
@ -267,3 +268,29 @@ func (t *Object) Clone() core.Cloneable {
|
||||
|
||||
return cloned
|
||||
}
|
||||
|
||||
func (t *Object) GetIn(ctx context.Context, path []core.Value) (core.Value, error) {
|
||||
if len(path) == 0 {
|
||||
return None, nil
|
||||
}
|
||||
|
||||
if typ := path[0].Type(); typ != types.String {
|
||||
return None, core.TypeError(typ, types.String)
|
||||
}
|
||||
|
||||
first, _ := t.Get(path[0].(String))
|
||||
|
||||
if len(path) == 1 {
|
||||
return first, nil
|
||||
}
|
||||
|
||||
getter, ok := first.(core.Getter)
|
||||
if !ok {
|
||||
return None, core.TypeError(
|
||||
first.Type(),
|
||||
core.NewType("Getter"),
|
||||
)
|
||||
}
|
||||
|
||||
return getter.GetIn(ctx, path[1:])
|
||||
}
|
||||
|
@ -1,11 +1,13 @@
|
||||
package values_test
|
||||
|
||||
import (
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values/types"
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values/types"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
@ -408,4 +410,86 @@ func TestObject(t *testing.T) {
|
||||
So(nestedInObjArr.Compare(nestedInCloneArr), ShouldNotEqual, 0)
|
||||
})
|
||||
})
|
||||
|
||||
Convey(".GetIn", t, func() {
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
Convey("Should return the same as .Get when input is correct", func() {
|
||||
|
||||
Convey("Should return item by key", func() {
|
||||
key := values.NewString("foo")
|
||||
obj := values.NewObjectWith(
|
||||
values.NewObjectProperty(key.String(), values.NewInt(1)),
|
||||
)
|
||||
|
||||
el, err := obj.GetIn(ctx, []core.Value{key})
|
||||
elGet, _ := obj.Get(key)
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(el.Compare(elGet), ShouldEqual, 0)
|
||||
})
|
||||
|
||||
Convey("Should return None when no items", func() {
|
||||
key := values.NewString("foo")
|
||||
obj := values.NewObject()
|
||||
|
||||
el, err := obj.GetIn(ctx, []core.Value{key})
|
||||
elGet, _ := obj.Get(key)
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(el.Compare(elGet), ShouldEqual, 0)
|
||||
})
|
||||
})
|
||||
|
||||
Convey("Should error when input is not correct", func() {
|
||||
|
||||
Convey("Should error when path[0] is not a string", func() {
|
||||
obj := values.NewObject()
|
||||
path := []core.Value{values.NewInt(0)}
|
||||
|
||||
el, err := obj.GetIn(ctx, path)
|
||||
|
||||
So(err, ShouldBeError)
|
||||
So(el.Compare(values.None), ShouldEqual, 0)
|
||||
})
|
||||
|
||||
Convey("Should error when first received item is not a Getter and len(path) > 1", func() {
|
||||
key := values.NewString("foo")
|
||||
obj := values.NewObjectWith(
|
||||
values.NewObjectProperty(key.String(), values.NewInt(1)),
|
||||
)
|
||||
path := []core.Value{key, key}
|
||||
|
||||
el, err := obj.GetIn(ctx, path)
|
||||
|
||||
So(err, ShouldBeError)
|
||||
So(el.Compare(values.None), ShouldEqual, 0)
|
||||
})
|
||||
})
|
||||
|
||||
Convey("Should return None when len(path) == 0", func() {
|
||||
obj := values.NewObject()
|
||||
|
||||
el, err := obj.GetIn(ctx, nil)
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(el.Compare(values.None), ShouldEqual, 0)
|
||||
})
|
||||
|
||||
Convey("Should call the nested Getter", func() {
|
||||
key := values.NewString("foo")
|
||||
obj := values.NewObjectWith(
|
||||
values.NewObjectProperty(key.String(), values.NewArrayWith(key)),
|
||||
)
|
||||
|
||||
el, err := obj.GetIn(ctx, []core.Value{
|
||||
key, // obj.foo
|
||||
values.NewInt(0), // obj.foo[0]
|
||||
})
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(el.Compare(key), ShouldEqual, 0)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
|
||||
// Click dispatches click event on a given element
|
||||
// @param source (Open | GetElement) - Event source.
|
||||
// @param selector (String, optional) - Optional selector. Only used when a document instance is passed.
|
||||
// @param selector (String, optional) - Optional selector.
|
||||
func Click(ctx context.Context, args ...core.Value) (core.Value, error) {
|
||||
err := core.ValidateArgs(args, 1, 2)
|
||||
|
||||
@ -18,26 +18,20 @@ func Click(ctx context.Context, args ...core.Value) (core.Value, error) {
|
||||
return values.False, err
|
||||
}
|
||||
|
||||
// CLICK(el)
|
||||
if len(args) == 1 {
|
||||
el, err := drivers.ToElement(args[0])
|
||||
|
||||
if err != nil {
|
||||
return values.False, err
|
||||
}
|
||||
|
||||
return values.True, el.Click(ctx)
|
||||
}
|
||||
|
||||
// CLICK(doc, selector)
|
||||
doc, err := drivers.ToDocument(args[0])
|
||||
el, err := drivers.ToElement(args[0])
|
||||
|
||||
if err != nil {
|
||||
return values.False, err
|
||||
}
|
||||
|
||||
// CLICK(elOrDoc)
|
||||
if len(args) == 1 {
|
||||
return values.True, el.Click(ctx)
|
||||
}
|
||||
|
||||
// CLICK(doc, selector)
|
||||
selector := values.ToString(args[1])
|
||||
exists, err := doc.ExistsBySelector(ctx, selector)
|
||||
exists, err := el.ExistsBySelector(ctx, selector)
|
||||
|
||||
if err != nil {
|
||||
return values.False, err
|
||||
@ -47,5 +41,5 @@ func Click(ctx context.Context, args ...core.Value) (core.Value, error) {
|
||||
return exists, nil
|
||||
}
|
||||
|
||||
return exists, doc.ClickBySelector(ctx, selector)
|
||||
return exists, el.ClickBySelector(ctx, selector)
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ func ClickAll(ctx context.Context, args ...core.Value) (core.Value, error) {
|
||||
return values.False, err
|
||||
}
|
||||
|
||||
doc, err := drivers.ToDocument(args[0])
|
||||
el, err := drivers.ToElement(args[0])
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
@ -27,7 +27,7 @@ func ClickAll(ctx context.Context, args ...core.Value) (core.Value, error) {
|
||||
|
||||
selector := values.ToString(args[1])
|
||||
|
||||
exists, err := doc.ExistsBySelector(ctx, selector)
|
||||
exists, err := el.ExistsBySelector(ctx, selector)
|
||||
|
||||
if err != nil {
|
||||
return values.False, err
|
||||
@ -37,5 +37,5 @@ func ClickAll(ctx context.Context, args ...core.Value) (core.Value, error) {
|
||||
return values.False, nil
|
||||
}
|
||||
|
||||
return values.True, doc.ClickBySelectorAll(ctx, selector)
|
||||
return values.True, el.ClickBySelectorAll(ctx, selector)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user