mirror of
https://github.com/MontFerret/ferret.git
synced 2024-12-12 11:15:14 +02:00
parent
376ad77404
commit
82f7317ebe
9
e2e/tests/doc_wait_attr_all_d.fql
Normal file
9
e2e/tests/doc_wait_attr_all_d.fql
Normal file
@ -0,0 +1,9 @@
|
||||
LET url = @dynamic + "?redirect=/events"
|
||||
LET doc = DOCUMENT(url, true)
|
||||
|
||||
WAIT_ELEMENT(doc, "#page-events")
|
||||
|
||||
CLICK_ALL(doc, "#wait-class-btn, #wait-class-random-btn")
|
||||
WAIT_ATTR_ALL(doc, "#wait-class-content, #wait-class-random-content", "class", "alert alert-success", 10000)
|
||||
|
||||
RETURN ""
|
18
e2e/tests/doc_wait_attr_d.fql
Normal file
18
e2e/tests/doc_wait_attr_d.fql
Normal file
@ -0,0 +1,18 @@
|
||||
LET url = @dynamic + "?redirect=/events"
|
||||
LET doc = DOCUMENT(url, true)
|
||||
LET selector = "#wait-class-btn"
|
||||
LET attrName = "data-ferret-x"
|
||||
LET attrVal = "foobar"
|
||||
|
||||
WAIT_ELEMENT(doc, "#page-events")
|
||||
|
||||
LET el = ELEMENT(doc, selector)
|
||||
LET prev = el.attributes
|
||||
|
||||
ATTR_SET(el, attrName, attrVal)
|
||||
WAIT_ATTR(doc, selector, attrName, attrVal, 30000)
|
||||
//WAIT_ATTR(el, attrName, attrVal)
|
||||
|
||||
LET curr = el.attributes
|
||||
|
||||
RETURN prev[attrName] == NONE && curr[attrName] == attrVal ? "" : "attributes should be updated"
|
16
e2e/tests/doc_wait_no_attr_d.fql
Normal file
16
e2e/tests/doc_wait_no_attr_d.fql
Normal file
@ -0,0 +1,16 @@
|
||||
LET url = @dynamic + "?redirect=/events"
|
||||
LET doc = DOCUMENT(url, true)
|
||||
|
||||
WAIT_ELEMENT(doc, "#page-events")
|
||||
|
||||
// with fixed timeout
|
||||
CLICK(doc, "#wait-no-class-btn")
|
||||
WAIT(1000)
|
||||
PRINT(ATTR_GET(ELEMENT(doc, "#wait-no-class-content"), "class"))
|
||||
WAIT_NO_ATTR(doc, "#wait-no-class-content", "class", "alert alert-success")
|
||||
|
||||
// with random timeout
|
||||
CLICK(doc, "#wait-no-class-random-btn")
|
||||
WAIT_NO_ATTR(doc, "#wait-no-class-random-content", "class", "alert alert-success", 10000)
|
||||
|
||||
RETURN ""
|
14
e2e/tests/el_wait_attr_2_d.fql
Normal file
14
e2e/tests/el_wait_attr_2_d.fql
Normal file
@ -0,0 +1,14 @@
|
||||
LET url = @dynamic + "?redirect=/events"
|
||||
LET doc = DOCUMENT(url, true)
|
||||
|
||||
WAIT_ELEMENT(doc, "#page-events")
|
||||
|
||||
LET el = ELEMENT(doc, "#wait-class-content")
|
||||
|
||||
ATTR_SET(el, "data-test", "test")
|
||||
WAIT_ATTR(el, "data-test", "test")
|
||||
|
||||
ATTR_REMOVE(el, "class")
|
||||
WAIT_ATTR(el, "class", NONE)
|
||||
|
||||
RETURN el.attributes.class == NONE ? "" : "attribute should be removed"
|
20
e2e/tests/el_wait_attr_d.fql
Normal file
20
e2e/tests/el_wait_attr_d.fql
Normal file
@ -0,0 +1,20 @@
|
||||
LET url = @dynamic + "?redirect=/events"
|
||||
LET doc = DOCUMENT(url, true)
|
||||
|
||||
WAIT_ELEMENT(doc, "#page-events")
|
||||
|
||||
// with fixed timeout
|
||||
LET b1 = ELEMENT(doc, "#wait-class-btn")
|
||||
LET c1 = ELEMENT(doc, "#wait-class-content")
|
||||
|
||||
CLICK(b1)
|
||||
WAIT_ATTR(c1, "class", "alert alert-success")
|
||||
|
||||
// with random timeout
|
||||
LET b2 = ELEMENT(doc, "#wait-class-random-btn")
|
||||
LET c2 = ELEMENT(doc, "#wait-class-random-content")
|
||||
|
||||
CLICK(b2)
|
||||
WAIT_ATTR(c2, "class", "alert alert-success", 10000)
|
||||
|
||||
RETURN ""
|
20
e2e/tests/el_wait_no_attr_d.fql
Normal file
20
e2e/tests/el_wait_no_attr_d.fql
Normal file
@ -0,0 +1,20 @@
|
||||
LET url = @dynamic + "?redirect=/events"
|
||||
LET doc = DOCUMENT(url, true)
|
||||
|
||||
WAIT_ELEMENT(doc, "#page-events")
|
||||
|
||||
// with fixed timeout
|
||||
LET b1 = ELEMENT(doc, "#wait-no-class-btn")
|
||||
LET c1 = ELEMENT(doc, "#wait-no-class-content")
|
||||
|
||||
CLICK(b1)
|
||||
WAIT_NO_ATTR(c1, "class", "alert alert-success")
|
||||
|
||||
// with random timeout
|
||||
LET b2 = ELEMENT(doc, "#wait-no-class-random-btn")
|
||||
LET c2 = ELEMENT(doc, "#wait-no-class-random-content")
|
||||
|
||||
CLICK(b2)
|
||||
WAIT_NO_ATTR(c2, "class", "alert alert-success", 10000)
|
||||
|
||||
RETURN ""
|
@ -10,6 +10,7 @@ import (
|
||||
"github.com/MontFerret/ferret/pkg/drivers"
|
||||
"github.com/MontFerret/ferret/pkg/drivers/cdp/eval"
|
||||
"github.com/MontFerret/ferret/pkg/drivers/cdp/events"
|
||||
"github.com/MontFerret/ferret/pkg/drivers/cdp/templates"
|
||||
"github.com/MontFerret/ferret/pkg/drivers/common"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/logging"
|
||||
@ -527,6 +528,13 @@ func (doc *HTMLDocument) MoveMouseByXY(ctx context.Context, x, y values.Float) e
|
||||
}
|
||||
|
||||
func (doc *HTMLDocument) WaitForElement(ctx context.Context, selector values.String, when drivers.WaitEvent) error {
|
||||
var operator string
|
||||
|
||||
if when == drivers.WaitEventPresence {
|
||||
operator = "!="
|
||||
} else {
|
||||
operator = "=="
|
||||
}
|
||||
|
||||
task := events.NewEvalWaitTask(
|
||||
doc.client,
|
||||
@ -542,7 +550,7 @@ func (doc *HTMLDocument) WaitForElement(ctx context.Context, selector values.Str
|
||||
return null;
|
||||
`,
|
||||
eval.ParamString(selector.String()),
|
||||
waitEventToEqOperator(when),
|
||||
operator,
|
||||
),
|
||||
events.DefaultPolling,
|
||||
)
|
||||
@ -555,26 +563,11 @@ func (doc *HTMLDocument) WaitForElement(ctx context.Context, selector values.Str
|
||||
func (doc *HTMLDocument) WaitForClassBySelector(ctx context.Context, selector, class values.String, when drivers.WaitEvent) error {
|
||||
task := events.NewEvalWaitTask(
|
||||
doc.client,
|
||||
fmt.Sprintf(`
|
||||
var el = document.querySelector(%s);
|
||||
|
||||
if (el == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var className = %s;
|
||||
var found = el.className.split(' ').find(i => i === className);
|
||||
|
||||
if (found %s null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// null means we need to repeat
|
||||
return null;
|
||||
`,
|
||||
eval.ParamString(selector.String()),
|
||||
eval.ParamString(class.String()),
|
||||
waitEventToEqOperator(when),
|
||||
templates.WaitBySelector(
|
||||
selector,
|
||||
when,
|
||||
class,
|
||||
fmt.Sprintf("el.className.split(' ').find(i => i === %s)", eval.ParamString(class.String())),
|
||||
),
|
||||
events.DefaultPolling,
|
||||
)
|
||||
@ -587,33 +580,11 @@ func (doc *HTMLDocument) WaitForClassBySelector(ctx context.Context, selector, c
|
||||
func (doc *HTMLDocument) WaitForClassBySelectorAll(ctx context.Context, selector, class values.String, when drivers.WaitEvent) error {
|
||||
task := events.NewEvalWaitTask(
|
||||
doc.client,
|
||||
fmt.Sprintf(`
|
||||
var elements = document.querySelectorAll(%s);
|
||||
|
||||
if (elements == null || elements.length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var className = %s;
|
||||
var foundCount = 0;
|
||||
|
||||
elements.forEach((el) => {
|
||||
var found = el.className.split(' ').find(i => i === className);
|
||||
if (found %s null) {
|
||||
foundCount++;
|
||||
}
|
||||
});
|
||||
|
||||
if (foundCount === elements.length) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// null means we need to repeat
|
||||
return null;
|
||||
`,
|
||||
eval.ParamString(selector.String()),
|
||||
eval.ParamString(class.String()),
|
||||
waitEventToEqOperator(when),
|
||||
templates.WaitBySelectorAll(
|
||||
selector,
|
||||
when,
|
||||
class,
|
||||
fmt.Sprintf("el.className.split(' ').find(i => i === %s)", eval.ParamString(class.String())),
|
||||
),
|
||||
events.DefaultPolling,
|
||||
)
|
||||
@ -641,6 +612,52 @@ func (doc *HTMLDocument) WaitForNavigation(ctx context.Context) error {
|
||||
}
|
||||
}
|
||||
|
||||
func (doc *HTMLDocument) WaitForAttributeBySelector(
|
||||
ctx context.Context,
|
||||
selector,
|
||||
name values.String,
|
||||
value core.Value,
|
||||
when drivers.WaitEvent,
|
||||
) error {
|
||||
task := events.NewEvalWaitTask(
|
||||
doc.client,
|
||||
templates.WaitBySelector(
|
||||
selector,
|
||||
when,
|
||||
value,
|
||||
templates.AttributeRead(name),
|
||||
),
|
||||
events.DefaultPolling,
|
||||
)
|
||||
|
||||
_, err := task.Run(ctx)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (doc *HTMLDocument) WaitForAttributeBySelectorAll(
|
||||
ctx context.Context,
|
||||
selector,
|
||||
name values.String,
|
||||
value core.Value,
|
||||
when drivers.WaitEvent,
|
||||
) error {
|
||||
task := events.NewEvalWaitTask(
|
||||
doc.client,
|
||||
templates.WaitBySelectorAll(
|
||||
selector,
|
||||
when,
|
||||
value,
|
||||
templates.AttributeRead(name),
|
||||
),
|
||||
events.DefaultPolling,
|
||||
)
|
||||
|
||||
_, err := task.Run(ctx)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (doc *HTMLDocument) Navigate(ctx context.Context, url values.String) error {
|
||||
if url == "" {
|
||||
url = BlankPageURL
|
||||
|
@ -861,6 +861,42 @@ func (el *HTMLElement) WaitForClass(ctx context.Context, class values.String, wh
|
||||
return err
|
||||
}
|
||||
|
||||
func (el *HTMLElement) WaitForAttribute(
|
||||
ctx context.Context,
|
||||
name values.String,
|
||||
value core.Value,
|
||||
when drivers.WaitEvent,
|
||||
) error {
|
||||
task := events.NewWaitTask(
|
||||
func(ctx2 context.Context) (core.Value, error) {
|
||||
current := el.GetAttribute(ctx2, name)
|
||||
|
||||
if when == drivers.WaitEventPresence {
|
||||
// Values appeared, exit
|
||||
if current.Compare(value) == 0 {
|
||||
// The value does not really matter if it's not None
|
||||
// None indicates that operation needs to be repeated
|
||||
return values.True, nil
|
||||
}
|
||||
} else {
|
||||
// Value disappeared, exit
|
||||
if current.Compare(value) != 0 {
|
||||
// The value does not really matter if it's not None
|
||||
// None indicates that operation needs to be repeated
|
||||
return values.True, nil
|
||||
}
|
||||
}
|
||||
|
||||
return values.None, nil
|
||||
},
|
||||
events.DefaultPolling,
|
||||
)
|
||||
|
||||
_, err := task.Run(ctx)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (el *HTMLElement) Click(ctx context.Context) (values.Boolean, error) {
|
||||
return events.DispatchEvent(ctx, el.client, el.id.objectID, "click")
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
@ -16,14 +15,6 @@ func PrepareEval(exp string) string {
|
||||
return fmt.Sprintf("((function () {%s})())", exp)
|
||||
}
|
||||
|
||||
func ParamString(param string) string {
|
||||
return "`" + param + "`"
|
||||
}
|
||||
|
||||
func ParamFloat(param float64) string {
|
||||
return strconv.FormatFloat(param, 'f', 6, 64)
|
||||
}
|
||||
|
||||
func Eval(ctx context.Context, client *cdp.Client, exp string, ret bool, async bool) (core.Value, error) {
|
||||
args := runtime.
|
||||
NewEvaluateArgs(PrepareEval(exp)).
|
||||
|
36
pkg/drivers/cdp/eval/param.go
Normal file
36
pkg/drivers/cdp/eval/param.go
Normal file
@ -0,0 +1,36 @@
|
||||
package eval
|
||||
|
||||
import (
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func Param(input core.Value) string {
|
||||
switch value := input.(type) {
|
||||
case values.String:
|
||||
return ParamString(string(value))
|
||||
case values.Float:
|
||||
return ParamFloat(float64(value))
|
||||
case values.Int:
|
||||
return ParamInt(int64(value))
|
||||
default:
|
||||
if input == values.None {
|
||||
return "null"
|
||||
}
|
||||
|
||||
return value.String()
|
||||
}
|
||||
}
|
||||
|
||||
func ParamString(param string) string {
|
||||
return `"` + param + `"`
|
||||
}
|
||||
|
||||
func ParamFloat(param float64) string {
|
||||
return strconv.FormatFloat(param, 'f', 6, 64)
|
||||
}
|
||||
|
||||
func ParamInt(param int64) string {
|
||||
return strconv.FormatInt(param, 64)
|
||||
}
|
@ -7,7 +7,6 @@ import (
|
||||
"math"
|
||||
"strings"
|
||||
|
||||
"github.com/MontFerret/ferret/pkg/drivers"
|
||||
"github.com/MontFerret/ferret/pkg/drivers/cdp/eval"
|
||||
"github.com/MontFerret/ferret/pkg/drivers/cdp/events"
|
||||
"github.com/MontFerret/ferret/pkg/drivers/common"
|
||||
@ -403,11 +402,3 @@ func createEventBroker(client *cdp.Client) (*events.EventBroker, error) {
|
||||
|
||||
return broker, nil
|
||||
}
|
||||
|
||||
func waitEventToEqOperator(when drivers.WaitEvent) string {
|
||||
if when == drivers.WaitEventAbsence {
|
||||
return "=="
|
||||
}
|
||||
|
||||
return "!="
|
||||
}
|
||||
|
14
pkg/drivers/cdp/templates/attributes.go
Normal file
14
pkg/drivers/cdp/templates/attributes.go
Normal file
@ -0,0 +1,14 @@
|
||||
package templates
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/MontFerret/ferret/pkg/drivers/cdp/eval"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
)
|
||||
|
||||
func AttributeRead(name values.String) string {
|
||||
n := name.String()
|
||||
return fmt.Sprintf(`
|
||||
el.attributes[%s] != null ? el.attributes[%s].value : null
|
||||
`, eval.ParamString(n), eval.ParamString(n))
|
||||
}
|
13
pkg/drivers/cdp/templates/helpers.go
Normal file
13
pkg/drivers/cdp/templates/helpers.go
Normal file
@ -0,0 +1,13 @@
|
||||
package templates
|
||||
|
||||
import (
|
||||
"github.com/MontFerret/ferret/pkg/drivers"
|
||||
)
|
||||
|
||||
func WaitEventToEqOperator(when drivers.WaitEvent) string {
|
||||
if when == drivers.WaitEventPresence {
|
||||
return "=="
|
||||
}
|
||||
|
||||
return "!="
|
||||
}
|
36
pkg/drivers/cdp/templates/wait_by_selector.go
Normal file
36
pkg/drivers/cdp/templates/wait_by_selector.go
Normal file
@ -0,0 +1,36 @@
|
||||
package templates
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/MontFerret/ferret/pkg/drivers"
|
||||
"github.com/MontFerret/ferret/pkg/drivers/cdp/eval"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
)
|
||||
|
||||
func WaitBySelector(selector values.String, when drivers.WaitEvent, value core.Value, check string) string {
|
||||
return fmt.Sprintf(
|
||||
`
|
||||
var el = document.querySelector(%s); // selector
|
||||
|
||||
if (el == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var result = %s; // check
|
||||
|
||||
// when value
|
||||
if (result %s %s) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// null means we need to repeat
|
||||
return null;
|
||||
`,
|
||||
eval.ParamString(selector.String()),
|
||||
check,
|
||||
WaitEventToEqOperator(when),
|
||||
eval.Param(value),
|
||||
)
|
||||
}
|
43
pkg/drivers/cdp/templates/wait_by_selector_all.go
Normal file
43
pkg/drivers/cdp/templates/wait_by_selector_all.go
Normal file
@ -0,0 +1,43 @@
|
||||
package templates
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/MontFerret/ferret/pkg/drivers/cdp/eval"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
|
||||
"github.com/MontFerret/ferret/pkg/drivers"
|
||||
)
|
||||
|
||||
func WaitBySelectorAll(selector values.String, when drivers.WaitEvent, value core.Value, check string) string {
|
||||
return fmt.Sprintf(`
|
||||
var elements = document.querySelectorAll(%s); // selector
|
||||
|
||||
if (elements == null || elements.length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var resultCount = 0;
|
||||
|
||||
elements.forEach((el) => {
|
||||
var result = %s; // check
|
||||
|
||||
// when
|
||||
if (result %s %s) {
|
||||
resultCount++;
|
||||
}
|
||||
});
|
||||
|
||||
if (resultCount === elements.length) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// null means we need to repeat
|
||||
return null;
|
||||
`,
|
||||
eval.ParamString(selector.String()),
|
||||
check,
|
||||
WaitEventToEqOperator(when),
|
||||
eval.Param(value),
|
||||
)
|
||||
}
|
@ -237,6 +237,14 @@ func (doc *HTMLDocument) WaitForClassBySelectorAll(_ context.Context, _, _ value
|
||||
return core.ErrNotSupported
|
||||
}
|
||||
|
||||
func (doc *HTMLDocument) WaitForAttributeBySelector(_ context.Context, _, _ values.String, _ core.Value, _ drivers.WaitEvent) error {
|
||||
return core.ErrNotSupported
|
||||
}
|
||||
|
||||
func (doc *HTMLDocument) WaitForAttributeBySelectorAll(_ context.Context, _, _ values.String, _ core.Value, _ drivers.WaitEvent) error {
|
||||
return core.ErrNotSupported
|
||||
}
|
||||
|
||||
func (doc *HTMLDocument) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
@ -406,6 +406,10 @@ func (el *HTMLElement) WaitForClass(_ context.Context, _ values.String, _ driver
|
||||
return core.ErrNotSupported
|
||||
}
|
||||
|
||||
func (el *HTMLElement) WaitForAttribute(_ context.Context, _ values.String, _ core.Value, _ drivers.WaitEvent) error {
|
||||
return core.ErrNotSupported
|
||||
}
|
||||
|
||||
func (el *HTMLElement) ensureStyles(ctx context.Context) error {
|
||||
if el.styles == nil {
|
||||
styles, err := el.parseStyles(ctx)
|
||||
|
@ -92,6 +92,8 @@ type (
|
||||
Hover(ctx context.Context) error
|
||||
|
||||
WaitForClass(ctx context.Context, class values.String, when WaitEvent) error
|
||||
|
||||
WaitForAttribute(ctx context.Context, name values.String, value core.Value, when WaitEvent) error
|
||||
}
|
||||
|
||||
// The Document interface represents any web page loaded in the browser
|
||||
@ -142,6 +144,10 @@ type (
|
||||
WaitForClassBySelector(ctx context.Context, selector, class values.String, when WaitEvent) error
|
||||
|
||||
WaitForClassBySelectorAll(ctx context.Context, selector, class values.String, when WaitEvent) error
|
||||
|
||||
WaitForAttributeBySelector(ctx context.Context, selector, name values.String, value core.Value, when WaitEvent) error
|
||||
|
||||
WaitForAttributeBySelectorAll(ctx context.Context, selector, name values.String, value core.Value, when WaitEvent) error
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -46,6 +46,10 @@ func NewLib() map[string]core.Function {
|
||||
"STYLE_GET": StyleGet,
|
||||
"STYLE_REMOVE": StyleRemove,
|
||||
"STYLE_SET": StyleSet,
|
||||
"WAIT_ATTR": WaitAttribute,
|
||||
"WAIT_NO_ATTR": WaitNoAttribute,
|
||||
"WAIT_ATTR_ALL": WaitAttributeAll,
|
||||
"WAIT_NO_ATTR_ALL": WaitNoAttributeAll,
|
||||
"WAIT_ELEMENT": WaitElement,
|
||||
"WAIT_NO_ELEMENT": WaitNoElement,
|
||||
"WAIT_CLASS": WaitClass,
|
||||
|
100
pkg/stdlib/html/wait_attr.go
Normal file
100
pkg/stdlib/html/wait_attr.go
Normal file
@ -0,0 +1,100 @@
|
||||
package html
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/MontFerret/ferret/pkg/drivers"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values/types"
|
||||
)
|
||||
|
||||
func WaitAttribute(ctx context.Context, args ...core.Value) (core.Value, error) {
|
||||
return waitAttributeWhen(ctx, args, drivers.WaitEventPresence)
|
||||
}
|
||||
|
||||
func WaitNoAttribute(ctx context.Context, args ...core.Value) (core.Value, error) {
|
||||
return waitAttributeWhen(ctx, args, drivers.WaitEventAbsence)
|
||||
}
|
||||
|
||||
func waitAttributeWhen(ctx context.Context, args []core.Value, when drivers.WaitEvent) (core.Value, error) {
|
||||
err := core.ValidateArgs(args, 3, 5)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
// document or element
|
||||
arg1 := args[0]
|
||||
err = core.ValidateType(arg1, drivers.HTMLDocumentType, drivers.HTMLElementType)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
// selector or attr name
|
||||
err = core.ValidateType(args[1], types.String)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
timeout := values.NewInt(defaultTimeout)
|
||||
|
||||
// if a document is passed
|
||||
// WAIT_ATTR(doc, selector, attrName, attrValue, timeout)
|
||||
if arg1.Type() == drivers.HTMLDocumentType {
|
||||
// revalidate args with more accurate amount
|
||||
err := core.ValidateArgs(args, 4, 5)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
// attr name
|
||||
err = core.ValidateType(args[2], types.String)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
doc := arg1.(drivers.HTMLDocument)
|
||||
selector := args[1].(values.String)
|
||||
name := args[2].(values.String)
|
||||
value := args[3]
|
||||
|
||||
if len(args) == 5 {
|
||||
err = core.ValidateType(args[4], types.Int)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
timeout = args[4].(values.Int)
|
||||
}
|
||||
|
||||
ctx, fn := waitTimeout(ctx, timeout)
|
||||
defer fn()
|
||||
|
||||
return values.None, doc.WaitForAttributeBySelector(ctx, selector, name, value, when)
|
||||
}
|
||||
|
||||
el := arg1.(drivers.HTMLElement)
|
||||
name := args[1].(values.String)
|
||||
value := args[2]
|
||||
|
||||
if len(args) == 4 {
|
||||
err = core.ValidateType(args[3], types.Int)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
timeout = args[3].(values.Int)
|
||||
}
|
||||
|
||||
ctx, fn := waitTimeout(ctx, timeout)
|
||||
defer fn()
|
||||
|
||||
return values.None, el.WaitForAttribute(ctx, name, value, when)
|
||||
}
|
77
pkg/stdlib/html/wait_attr_all.go
Normal file
77
pkg/stdlib/html/wait_attr_all.go
Normal file
@ -0,0 +1,77 @@
|
||||
package html
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/MontFerret/ferret/pkg/drivers"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values/types"
|
||||
)
|
||||
|
||||
// WaitClassAll waits for a class to appear on all matched elements.
|
||||
// Stops the execution until the navigation ends or operation times out.
|
||||
// @param doc (HTMLDocument) - Parent document.
|
||||
// @param selector (String) - String of CSS selector.
|
||||
// @param class (String) - String of target CSS class.
|
||||
// @param timeout (Int, optional) - Optional timeout.
|
||||
func WaitAttributeAll(ctx context.Context, args ...core.Value) (core.Value, error) {
|
||||
return waitAttributeAllWhen(ctx, args, drivers.WaitEventPresence)
|
||||
}
|
||||
|
||||
// WaitClassAll waits for a class to disappear on all matched elements.
|
||||
// Stops the execution until the navigation ends or operation times out.
|
||||
// @param doc (HTMLDocument) - Parent document.
|
||||
// @param selector (String) - String of CSS selector.
|
||||
// @param class (String) - String of target CSS class.
|
||||
// @param timeout (Int, optional) - Optional timeout.
|
||||
func WaitNoAttributeAll(ctx context.Context, args ...core.Value) (core.Value, error) {
|
||||
return waitAttributeAllWhen(ctx, args, drivers.WaitEventAbsence)
|
||||
}
|
||||
|
||||
func waitAttributeAllWhen(ctx context.Context, args []core.Value, when drivers.WaitEvent) (core.Value, error) {
|
||||
err := core.ValidateArgs(args, 4, 5)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
doc, err := toDocument(args[0])
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
// selector
|
||||
err = core.ValidateType(args[1], types.String)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
// attr name
|
||||
err = core.ValidateType(args[2], types.String)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
selector := args[1].(values.String)
|
||||
name := args[2].(values.String)
|
||||
value := args[3]
|
||||
timeout := values.NewInt(defaultTimeout)
|
||||
|
||||
if len(args) == 5 {
|
||||
err = core.ValidateType(args[4], types.Int)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
timeout = args[4].(values.Int)
|
||||
}
|
||||
|
||||
ctx, fn := waitTimeout(ctx, timeout)
|
||||
defer fn()
|
||||
|
||||
return values.None, doc.WaitForAttributeBySelectorAll(ctx, selector, name, value, when)
|
||||
}
|
Loading…
Reference in New Issue
Block a user