1
0
mirror of https://github.com/MontFerret/ferret.git synced 2025-05-31 23:09:43 +02:00

Feature/#250 wait style 2 (#260)

* Added WAIT_STYLE and WAIT_NO_STYLE

* Added WAIT_NO_STYLE and WAIT_NO_STYLE_ALL functions
This commit is contained in:
Tim Voronov 2019-03-14 22:10:15 -04:00 committed by GitHub
parent 82f7317ebe
commit e17ce5a3d5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 411 additions and 28 deletions

View File

@ -0,0 +1,30 @@
LET url = @dynamic + "?redirect=/events"
LET doc = DOCUMENT(url, true)
LET selector = "#wait-class-btn, #wait-class-random-btn"
WAIT_ELEMENT(doc, "#page-events")
LET n = (
FOR el IN ELEMENTS(doc, selector)
ATTR_SET(el, "style", "color: black")
RETURN NONE
)
WAIT_STYLE_ALL(doc, selector, "color", "black", 10000)
LET n2 = (
FOR el IN ELEMENTS(doc, selector)
ATTR_SET(el, "style", "color: red")
RETURN NONE
)
WAIT_NO_STYLE_ALL(doc, selector, "color", "black", 10000)
LET results = (
FOR el IN ELEMENTS(doc, selector)
RETURN el.style.color
)
RETURN CONCAT(results) == "redred" ? "" : "styles should be updated"

View File

@ -0,0 +1,19 @@
LET url = @dynamic + "?redirect=/events"
LET doc = DOCUMENT(url, true)
LET selector = "#wait-class-btn"
WAIT_ELEMENT(doc, "#page-events")
LET el = ELEMENT(doc, selector)
ATTR_SET(el, "style", "width: 100%")
WAIT_STYLE(doc, selector, "width", "100%")
LET prev = el.style
ATTR_SET(el, "style", "width: 50%")
WAIT_NO_STYLE(doc, selector, "width", "100%")
LET curr = el.style
RETURN prev.width == "100%" && curr.width == "50%" ? "" : "style should be changed"

View File

@ -0,0 +1,21 @@
LET url = @dynamic + "?redirect=/events"
LET doc = DOCUMENT(url, true)
LET selector = "#wait-class-btn, #wait-class-random-btn"
WAIT_ELEMENT(doc, "#page-events")
LET n = (
FOR el IN ELEMENTS(doc, selector)
ATTR_SET(el, "style", "color: black")
RETURN NONE
)
WAIT_STYLE_ALL(doc, selector, "color", "black", 10000)
LET results = (
FOR el IN ELEMENTS(doc, selector)
RETURN el.style.color
)
RETURN CONCAT(results) == "blackblack" ? "" : "styles should be updated"

View File

@ -0,0 +1,15 @@
LET url = @dynamic + "?redirect=/events"
LET doc = DOCUMENT(url, true)
LET selector = "#wait-class-btn"
WAIT_ELEMENT(doc, "#page-events")
LET el = ELEMENT(doc, selector)
LET prev = el.style
ATTR_SET(el, "style", "width: 100%")
WAIT_STYLE(doc, selector, "width", "100%")
LET curr = el.style
RETURN prev.width == NONE && curr.width == "100%" ? "" : "style should be updated"

View File

@ -0,0 +1,18 @@
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, "style", "color: black")
WAIT_STYLE(el, "color", "black")
LET prev = el.style
ATTR_SET(el, "style", "color: red")
WAIT_NO_STYLE(el, "color", "black")
LET curr = el.style
RETURN prev.color == "black" && curr.color == "red" ? "" : "style should be changed"

View File

@ -0,0 +1,18 @@
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, "style", "color: black")
WAIT_STYLE(el, "color", "black")
LET prev = el.style
ATTR_REMOVE(el, "style")
WAIT_STYLE(el, "color", NONE)
LET curr = el.style
RETURN prev.color == "black" && curr.color == NONE ? "" : "style should be removed"

View File

@ -658,6 +658,40 @@ func (doc *HTMLDocument) WaitForAttributeBySelectorAll(
return err
}
func (doc *HTMLDocument) WaitForStyleBySelector(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.StyleRead(name),
),
events.DefaultPolling,
)
_, err := task.Run(ctx)
return err
}
func (doc *HTMLDocument) WaitForStyleBySelectorAll(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.StyleRead(name),
),
events.DefaultPolling,
)
_, err := task.Run(ctx)
return err
}
func (doc *HTMLDocument) Navigate(ctx context.Context, url values.String) error {
if url == "" {
url = BlankPageURL

View File

@ -867,30 +867,19 @@ func (el *HTMLElement) WaitForAttribute(
value core.Value,
when drivers.WaitEvent,
) error {
task := events.NewWaitTask(
func(ctx2 context.Context) (core.Value, error) {
current := el.GetAttribute(ctx2, name)
task := events.NewValueWaitTask(when, value, func(ctx context.Context) (core.Value, error) {
return el.GetAttribute(ctx, name), nil
}, events.DefaultPolling)
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
}
}
_, err := task.Run(ctx)
return values.None, nil
},
events.DefaultPolling,
)
return err
}
func (el *HTMLElement) WaitForStyle(ctx context.Context, name values.String, value core.Value, when drivers.WaitEvent) error {
task := events.NewValueWaitTask(when, value, func(ctx context.Context) (core.Value, error) {
return el.GetStyle(ctx, name)
}, events.DefaultPolling)
_, err := task.Run(ctx)

View File

@ -2,6 +2,7 @@ package events
import (
"context"
"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"
@ -74,3 +75,39 @@ func NewEvalWaitTask(
polling,
)
}
func NewValueWaitTask(
when drivers.WaitEvent,
value core.Value,
getter Function,
polling time.Duration,
) *WaitTask {
return &WaitTask{
func(ctx context.Context) (core.Value, error) {
current, err := getter(ctx)
if err != nil {
return values.None, err
}
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
},
polling,
}
}

View File

@ -0,0 +1,15 @@
package templates
import (
"fmt"
"github.com/MontFerret/ferret/pkg/drivers/cdp/eval"
"github.com/MontFerret/ferret/pkg/runtime/values"
)
func StyleRead(name values.String) string {
n := name.String()
return fmt.Sprintf(`
el.style[%s] != "" ? el.style[%s] : null
`, eval.ParamString(n), eval.ParamString(n))
}

View File

@ -245,6 +245,14 @@ func (doc *HTMLDocument) WaitForAttributeBySelectorAll(_ context.Context, _, _ v
return core.ErrNotSupported
}
func (doc *HTMLDocument) WaitForStyleBySelector(_ context.Context, _, _ values.String, _ core.Value, _ drivers.WaitEvent) error {
return core.ErrNotSupported
}
func (doc *HTMLDocument) WaitForStyleBySelectorAll(_ context.Context, _, _ values.String, _ core.Value, _ drivers.WaitEvent) error {
return core.ErrNotSupported
}
func (doc *HTMLDocument) Close() error {
return nil
}

View File

@ -410,6 +410,10 @@ func (el *HTMLElement) WaitForAttribute(_ context.Context, _ values.String, _ co
return core.ErrNotSupported
}
func (el *HTMLElement) WaitForStyle(_ 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)

View File

@ -91,9 +91,11 @@ 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
WaitForStyle(ctx context.Context, name values.String, value core.Value, when WaitEvent) error
WaitForClass(ctx context.Context, class values.String, when WaitEvent) error
}
// The Document interface represents any web page loaded in the browser
@ -141,13 +143,17 @@ type (
WaitForElement(ctx context.Context, selector values.String, when WaitEvent) error
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
WaitForStyleBySelector(ctx context.Context, selector, name values.String, value core.Value, when WaitEvent) error
WaitForStyleBySelectorAll(ctx context.Context, selector, name values.String, value core.Value, when WaitEvent) error
WaitForClassBySelector(ctx context.Context, selector, class values.String, when WaitEvent) error
WaitForClassBySelectorAll(ctx context.Context, selector, class values.String, when WaitEvent) error
}
)

View File

@ -56,6 +56,10 @@ func NewLib() map[string]core.Function {
"WAIT_NO_CLASS": WaitNoClass,
"WAIT_CLASS_ALL": WaitClassAll,
"WAIT_NO_CLASS_ALL": WaitNoClassAll,
"WAIT_STYLE": WaitStyle,
"WAIT_NO_STYLE": WaitNoStyle,
"WAIT_STYLE_ALL": WaitStyleAll,
"WAIT_NO_STYLE_ALL": WaitNoStyleAll,
"WAIT_NAVIGATION": WaitNavigation,
}
}

View 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 WaitStyle(ctx context.Context, args ...core.Value) (core.Value, error) {
return waitStyleWhen(ctx, args, drivers.WaitEventPresence)
}
func WaitNoStyle(ctx context.Context, args ...core.Value) (core.Value, error) {
return waitStyleWhen(ctx, args, drivers.WaitEventAbsence)
}
func waitStyleWhen(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.WaitForStyleBySelector(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.WaitForStyle(ctx, name, value, when)
}

View File

@ -0,0 +1,65 @@
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 WaitStyleAll(ctx context.Context, args ...core.Value) (core.Value, error) {
return waitStyleAllWhen(ctx, args, drivers.WaitEventPresence)
}
func WaitNoStyleAll(ctx context.Context, args ...core.Value) (core.Value, error) {
return waitStyleAllWhen(ctx, args, drivers.WaitEventAbsence)
}
func waitStyleAllWhen(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.WaitForStyleBySelectorAll(ctx, selector, name, value, when)
}