Skip to content

Commit 9ba7527

Browse files
author
=
committed
merge with MontFerret/master
2 parents 5f57958 + 1866cb1 commit 9ba7527

20 files changed

+630
-119
lines changed

CHANGELOG.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
#### Added
55
- DateTime functions.
66
- ``PAGINATION`` function.
7-
- ``SCROLL_TOP`` and ``SCROLL_BOTTOM`` functions.
7+
- ``SCROLL_TOP``, ``SCROLL_BOTTOM`` and ``SCROLL_ELEMENT`` functions.
8+
- ``HOVER`` function.
89

910
#### Fixed
1011
- Unable to define variables and make function calls before FILTER, SORT and etc statements.

Gopkg.lock

+6-6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Gopkg.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343

4444
[[constraint]]
4545
name = "github.com/PuerkitoBio/goquery"
46-
version = "1.4.1"
46+
version = "1.5.0"
4747

4848
[[constraint]]
4949
name = "github.com/gofrs/uuid"
@@ -55,7 +55,7 @@
5555

5656
[[constraint]]
5757
name = "github.com/rs/zerolog"
58-
version = "1.10.2"
58+
version = "1.10.3"
5959

6060
[[constraint]]
6161
name = "github.com/natefinch/lumberjack"

e2e/pages/dynamic/components/app.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import Layout from './layout.js';
22
import IndexPage from './pages/index.js';
33
import FormsPage from './pages/forms/index.js';
4+
import EventsPage from './pages/events/index.js';
45

56
const e = React.createElement;
67
const Router = ReactRouter.Router;
@@ -21,7 +22,11 @@ export default function AppComponent({ redirect = null}) {
2122
e(Route, {
2223
path: '/forms',
2324
component: FormsPage
24-
})
25+
}),
26+
e(Route, {
27+
path: '/events',
28+
component: EventsPage
29+
}),
2530
]),
2631
redirect ? e(Redirect, { to: redirect }) : null
2732
])
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
const e = React.createElement;
2+
3+
export default class HoverableComponent extends React.PureComponent {
4+
constructor(props) {
5+
super(props);
6+
7+
this.state = {
8+
hovered: false
9+
};
10+
}
11+
12+
handleMouseEnter() {
13+
this.setState({
14+
hovered: true
15+
});
16+
}
17+
18+
handleMouseLeave() {
19+
this.setState({
20+
hovered: false
21+
});
22+
}
23+
24+
render() {
25+
const children = [];
26+
children.push(
27+
e("p", null, [
28+
e("a", {
29+
id: "hoverable-btn",
30+
className: "btn btn-primary",
31+
href: "#",
32+
onMouseEnter: this.handleMouseEnter.bind(this),
33+
onMouseLeave: this.handleMouseLeave.bind(this)
34+
}, [
35+
"Hoverable link"
36+
]),
37+
])
38+
);
39+
40+
if (this.state.hovered) {
41+
children.push(
42+
e("div", null, [
43+
e("div", { id: "hoverable-content", className: "card card-body"}, [
44+
"Lorem ipsum dolor sit amet."
45+
])
46+
])
47+
)
48+
}
49+
50+
return e("div", null, children);
51+
}
52+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import Hoverable from "./hoverable.js";
2+
3+
const e = React.createElement;
4+
5+
export default class EventsPage extends React.Component {
6+
render() {
7+
return e("div", { className: "row", id: "page-events" }, [
8+
e("div", { className: "col-lg-12"}, [
9+
e(Hoverable)
10+
])
11+
])
12+
}
13+
}

e2e/pages/dynamic/components/pages/forms/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ export default class FormsPage extends React.Component {
4545
}
4646

4747
render() {
48-
return e("form", null, [
48+
return e("form", { id: "page-form" }, [
4949
e("div", { className: "form-group" }, [
5050
e("label", null, "Text input"),
5151
e("input", {

e2e/tests/doc_hover_d.fql

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
LET url = @dynamic + "?redirect=/events"
2+
LET doc = DOCUMENT(url, true)
3+
4+
WAIT_ELEMENT(doc, "#page-events")
5+
6+
HOVER(doc, "#hoverable-btn")
7+
WAIT_ELEMENT(doc, "#hoverable-content")
8+
9+
LET output = INNER_TEXT(doc, "#hoverable-content")
10+
11+
RETURN EXPECT(output, "Lorem ipsum dolor sit amet.")

e2e/tests/el_hover_d.fql

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
LET url = @dynamic + "?redirect=/events"
2+
LET doc = DOCUMENT(url, true)
3+
4+
WAIT_ELEMENT(doc, "#page-events")
5+
6+
LET input = ELEMENT(doc, "#hoverable-btn")
7+
8+
HOVER(input)
9+
WAIT_ELEMENT(doc, "#hoverable-content")
10+
11+
LET output = ELEMENT(doc, "#hoverable-content")
12+
13+
RETURN EXPECT(output.innerText, "Lorem ipsum dolor sit amet.")

pkg/html/dynamic/document.go

+61-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package dynamic
33
import (
44
"context"
55
"fmt"
6+
"github.com/mafredri/cdp/protocol/dom"
67
"hash/fnv"
78
"sync"
89
"time"
@@ -531,6 +532,45 @@ func (doc *HTMLDocument) SelectBySelector(selector values.String, value *values.
531532
return nil, core.TypeError(core.ArrayType, res.Type())
532533
}
533534

535+
func (doc *HTMLDocument) HoverBySelector(selector values.String) error {
536+
ctx, cancel := contextWithTimeout()
537+
defer cancel()
538+
539+
err := doc.ScrollBySelector(selector)
540+
541+
if err != nil {
542+
return err
543+
}
544+
545+
selectorArgs := dom.NewQuerySelectorArgs(doc.element.id.nodeID, selector.String())
546+
found, err := doc.client.DOM.QuerySelector(ctx, selectorArgs)
547+
548+
if err != nil {
549+
doc.element.logError(err).
550+
Str("selector", selector.String()).
551+
Msg("failed to retrieve a node by selector")
552+
553+
return err
554+
}
555+
556+
if found.NodeID <= 0 {
557+
return errors.New("element not found")
558+
}
559+
560+
q, err := getClickablePoint(ctx, doc.client, &HTMLElementIdentity{
561+
nodeID: found.NodeID,
562+
})
563+
564+
if err != nil {
565+
return err
566+
}
567+
568+
return doc.client.Input.DispatchMouseEvent(
569+
ctx,
570+
input.NewDispatchMouseEventArgs("mouseMoved", q.X, q.Y),
571+
)
572+
}
573+
534574
func (doc *HTMLDocument) WaitForSelector(selector values.String, timeout values.Int) error {
535575
task := events.NewEvalWaitTask(
536576
doc.client,
@@ -815,7 +855,7 @@ func (doc *HTMLDocument) ScrollTop() error {
815855
window.scrollTo({
816856
left: 0,
817857
top: 0,
818-
behavior: 'smooth'
858+
behavior: 'instant'
819859
});
820860
`, false, false)
821861

@@ -827,13 +867,32 @@ func (doc *HTMLDocument) ScrollBottom() error {
827867
window.scrollTo({
828868
left: 0,
829869
top: window.document.body.scrollHeight,
830-
behavior: 'smooth'
870+
behavior: 'instant'
831871
});
832872
`, false, false)
833873

834874
return err
835875
}
836876

877+
func (doc *HTMLDocument) ScrollBySelector(selector values.String) error {
878+
_, err := eval.Eval(doc.client, fmt.Sprintf(`
879+
var el = document.querySelector(%s);
880+
881+
if (el == null) {
882+
throw new Error("element not found");
883+
}
884+
885+
el.scrollIntoView({
886+
behavior: 'instant'
887+
});
888+
889+
return true;
890+
`, eval.ParamString(selector.String()),
891+
), false, false)
892+
893+
return err
894+
}
895+
837896
func (doc *HTMLDocument) handlePageLoad(_ interface{}) {
838897
doc.Lock()
839898
defer doc.Unlock()

0 commit comments

Comments
 (0)