mirror of
https://github.com/MontFerret/ferret.git
synced 2025-11-06 08:39:09 +02:00
Feature/#229 wait no element (#249)
* Added possibility to wait for an element or a class absence
This commit is contained in:
15
e2e/main.go
15
e2e/main.go
@@ -1,12 +1,14 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"github.com/MontFerret/ferret/e2e/runner"
|
||||
"github.com/MontFerret/ferret/e2e/server"
|
||||
"github.com/rs/zerolog"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
)
|
||||
@@ -101,7 +103,18 @@ func main() {
|
||||
Filter: filterR,
|
||||
})
|
||||
|
||||
err := r.Run()
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, os.Interrupt)
|
||||
|
||||
go func() {
|
||||
for {
|
||||
<-c
|
||||
cancel()
|
||||
}
|
||||
}()
|
||||
|
||||
err := r.Run(ctx)
|
||||
|
||||
if err != nil {
|
||||
os.Exit(1)
|
||||
|
||||
42
e2e/pages/dynamic/components/pages/events/appearable.js
Normal file
42
e2e/pages/dynamic/components/pages/events/appearable.js
Normal file
@@ -0,0 +1,42 @@
|
||||
import random from "../../../utils/random.js";
|
||||
|
||||
const e = React.createElement;
|
||||
|
||||
function render(id) {
|
||||
return e("span", { id: `${id}-content` }, ["Hello world"]);
|
||||
}
|
||||
|
||||
export default class AppearableComponent extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
element: props.appear === true ? null : render(props.id)
|
||||
};
|
||||
}
|
||||
|
||||
handleClick() {
|
||||
setTimeout(() => {
|
||||
this.setState({
|
||||
element: this.props.appear === true ? render(this.props.id) : null
|
||||
})
|
||||
}, random())
|
||||
}
|
||||
|
||||
render() {
|
||||
const btnId = `${this.props.id}-btn`;
|
||||
|
||||
return e("div", {className: "card"}, [
|
||||
e("div", { className: "card-header"}, [
|
||||
e("button", {
|
||||
id: btnId,
|
||||
className: "btn btn-primary",
|
||||
onClick: this.handleClick.bind(this)
|
||||
}, [
|
||||
this.props.title || "Toggle class"
|
||||
])
|
||||
]),
|
||||
e("div", { className: "card-body"}, this.state.element)
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
import random from "../../../utils/random.js";
|
||||
|
||||
const e = React.createElement;
|
||||
|
||||
export default class ClickableComponent extends React.PureComponent {
|
||||
@@ -5,7 +7,7 @@ export default class ClickableComponent extends React.PureComponent {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
clicked: false
|
||||
show: props.show === true
|
||||
};
|
||||
}
|
||||
|
||||
@@ -13,12 +15,12 @@ export default class ClickableComponent extends React.PureComponent {
|
||||
let timeout = 500;
|
||||
|
||||
if (this.props.randomTimeout) {
|
||||
timeout = Math.ceil(Math.random() * 1000 * 10);
|
||||
timeout = random();
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
this.setState({
|
||||
clicked: !this.state.clicked
|
||||
show: !this.state.show
|
||||
})
|
||||
}, timeout)
|
||||
}
|
||||
@@ -28,7 +30,7 @@ export default class ClickableComponent extends React.PureComponent {
|
||||
const contentId = `${this.props.id}-content`;
|
||||
const classNames = ["alert"];
|
||||
|
||||
if (this.state.clicked) {
|
||||
if (this.state.show === true) {
|
||||
classNames.push("alert-success");
|
||||
}
|
||||
|
||||
@@ -39,7 +41,7 @@ export default class ClickableComponent extends React.PureComponent {
|
||||
className: "btn btn-primary",
|
||||
onClick: this.handleClick.bind(this)
|
||||
}, [
|
||||
"Toggle class"
|
||||
this.props.title || "Toggle class"
|
||||
])
|
||||
]),
|
||||
e("div", { className: "card-body"}, [
|
||||
|
||||
@@ -1,19 +1,60 @@
|
||||
import Hoverable from "./hoverable.js";
|
||||
import Clickable from "./clickable.js";
|
||||
import Appearable from "./appearable.js";
|
||||
|
||||
const e = React.createElement;
|
||||
|
||||
export default class EventsPage extends React.Component {
|
||||
render() {
|
||||
return e("div", { className: "row", id: "page-events" }, [
|
||||
e("div", { className: "col-lg-4"}, [
|
||||
e(Hoverable),
|
||||
return e("div", { id: "page-events" }, [
|
||||
e("div", { className: "row" }, [
|
||||
e("div", { className: "col-lg-4"}, [
|
||||
e(Hoverable),
|
||||
]),
|
||||
e("div", { className: "col-lg-4"}, [
|
||||
e(Clickable, {
|
||||
id: "wait-class",
|
||||
title: "Add class"
|
||||
})
|
||||
]),
|
||||
e("div", { className: "col-lg-4"}, [
|
||||
e(Clickable, {
|
||||
id: "wait-class-random",
|
||||
title: "Add class 2",
|
||||
randomTimeout: true
|
||||
})
|
||||
])
|
||||
]),
|
||||
e("div", { className: "col-lg-4"}, [
|
||||
e(Clickable, { id: "wait-class" })
|
||||
]),
|
||||
e("div", { className: "col-lg-4"}, [
|
||||
e(Clickable, { id: "wait-class-random", randomTimeout: true })
|
||||
e("div", { className: "row" }, [
|
||||
e("div", { className: "col-lg-4"}, [
|
||||
e(Clickable, {
|
||||
id: "wait-no-class",
|
||||
title: "Remove class",
|
||||
show: true
|
||||
})
|
||||
]),
|
||||
e("div", { className: "col-lg-4"}, [
|
||||
e(Clickable, {
|
||||
id: "wait-no-class-random",
|
||||
title: "Remove class 2",
|
||||
show: true,
|
||||
randomTimeout: true
|
||||
})
|
||||
]),
|
||||
e("div", { className: "col-lg-4"}, [
|
||||
e(Appearable, {
|
||||
id: "wait-element",
|
||||
appear: true,
|
||||
title: "Appearable"
|
||||
})
|
||||
]),
|
||||
e("div", { className: "col-lg-4"}, [
|
||||
e(Appearable, {
|
||||
id: "wait-no-element",
|
||||
appear: false,
|
||||
title: "Disappearable"
|
||||
})
|
||||
])
|
||||
])
|
||||
])
|
||||
}
|
||||
|
||||
13
e2e/pages/dynamic/utils/random.js
Normal file
13
e2e/pages/dynamic/utils/random.js
Normal file
@@ -0,0 +1,13 @@
|
||||
export default function random(min = 1000, max = 5000) {
|
||||
const val = Math.random() * 1000 * 10;
|
||||
|
||||
if (val < min) {
|
||||
return min;
|
||||
}
|
||||
|
||||
if (val > max) {
|
||||
return max;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
@@ -52,9 +52,7 @@ func New(logger zerolog.Logger, settings Settings) *Runner {
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Runner) Run() error {
|
||||
ctx := context.Background()
|
||||
|
||||
func (r *Runner) Run(ctx context.Context) error {
|
||||
ctx = drivers.WithContext(
|
||||
ctx,
|
||||
cdp.NewDriver(cdp.WithAddress(r.settings.CDPAddress)),
|
||||
|
||||
@@ -3,7 +3,7 @@ LET doc = DOCUMENT(url, true)
|
||||
|
||||
WAIT_ELEMENT(doc, "#page-events")
|
||||
|
||||
CLICK_ALL(doc, ".clickable button")
|
||||
WAIT_CLASS_ALL(doc, ".clickable .card-body div", "alert-success", 10000)
|
||||
CLICK_ALL(doc, "#wait-class-btn, #wait-class-random-btn")
|
||||
WAIT_CLASS_ALL(doc, "#wait-class-content, #wait-class-random-content", "alert-success", 10000)
|
||||
|
||||
RETURN ""
|
||||
13
e2e/tests/doc_wait_element_d.fql
Normal file
13
e2e/tests/doc_wait_element_d.fql
Normal file
@@ -0,0 +1,13 @@
|
||||
LET url = @dynamic + "?redirect=/events"
|
||||
LET doc = DOCUMENT(url, true)
|
||||
LET pageSelector = "#page-events"
|
||||
LET elemSelector = "#wait-element-content"
|
||||
LET btnSelector = "#wait-element-btn"
|
||||
|
||||
WAIT_ELEMENT(doc, pageSelector)
|
||||
|
||||
CLICK(doc, btnSelector)
|
||||
|
||||
WAIT_ELEMENT(doc, elemSelector, 10000)
|
||||
|
||||
RETURN ELEMENT_EXISTS(doc, elemSelector) ? "" : "element not found"
|
||||
9
e2e/tests/doc_wait_no_class_all_d.fql
Normal file
9
e2e/tests/doc_wait_no_class_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-no-class-btn, #wait-no-class-random-btn")
|
||||
WAIT_NO_CLASS_ALL(doc, "#wait-no-class-content, #wait-no-class-random-content", "alert-success", 10000)
|
||||
|
||||
RETURN ""
|
||||
14
e2e/tests/doc_wait_no_class_d.fql
Normal file
14
e2e/tests/doc_wait_no_class_d.fql
Normal file
@@ -0,0 +1,14 @@
|
||||
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_NO_CLASS(doc, "#wait-no-class-content", "alert-success")
|
||||
|
||||
// with random timeout
|
||||
CLICK(doc, "#wait-no-class-random-btn")
|
||||
WAIT_NO_CLASS(doc, "#wait-no-class-random-content", "alert-success", 10000)
|
||||
|
||||
RETURN ""
|
||||
13
e2e/tests/doc_wait_no_element_d.fql
Normal file
13
e2e/tests/doc_wait_no_element_d.fql
Normal file
@@ -0,0 +1,13 @@
|
||||
LET url = @dynamic + "?redirect=/events"
|
||||
LET doc = DOCUMENT(url, true)
|
||||
LET pageSelector = "#page-events"
|
||||
LET elemSelector = "#wait-no-element-content"
|
||||
LET btnSelector = "#wait-no-element-btn"
|
||||
|
||||
WAIT_ELEMENT(doc, pageSelector)
|
||||
|
||||
CLICK(doc, btnSelector)
|
||||
|
||||
WAIT_NO_ELEMENT(doc, elemSelector, 10000)
|
||||
|
||||
RETURN ELEMENT_EXISTS(doc, elemSelector) ? "element should not be found" : ""
|
||||
20
e2e/tests/el_wait_no_class_d.fql
Normal file
20
e2e/tests/el_wait_no_class_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_CLASS(c1, "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_CLASS(c2, "alert-success", 10000)
|
||||
|
||||
RETURN ""
|
||||
Reference in New Issue
Block a user