1
0
mirror of https://github.com/MontFerret/ferret.git synced 2025-11-06 08:39:09 +02:00

Feature/focus (#340)

* Added and implemented Focus and FocusBySelector methods

* Added e2e tests

* Updated CHANGELOG

* Fixed linting errors
This commit is contained in:
Tim Voronov
2019-07-23 16:13:04 -04:00
committed by GitHub
parent 996d565191
commit 7e6b3bf15d
12 changed files with 154 additions and 0 deletions

View File

@@ -11,6 +11,7 @@
- Regular expression operator. [#326](https://github.com/MontFerret/ferret/pull/326) - Regular expression operator. [#326](https://github.com/MontFerret/ferret/pull/326)
- ``INNER_HTML_SET`` and ``INNER_TEXT_SET`` functions. [#329](https://github.com/MontFerret/ferret/pull/329) - ``INNER_HTML_SET`` and ``INNER_TEXT_SET`` functions. [#329](https://github.com/MontFerret/ferret/pull/329)
- Possibility to set viewport size. [#334](https://github.com/MontFerret/ferret/pull/334) - Possibility to set viewport size. [#334](https://github.com/MontFerret/ferret/pull/334)
- ``FOCUS`` function. [#340](https://github.com/MontFerret/ferret/pull/340)
#### Changed #### Changed
- ``RAND`` accepts optional upper and lower limits. [#271](https://github.com/MontFerret/ferret/pull/271) - ``RAND`` accepts optional upper and lower limits. [#271](https://github.com/MontFerret/ferret/pull/271)

View File

@@ -0,0 +1,66 @@
import random from "../../../utils/random.js";
const e = React.createElement;
export default class FocusableComponent extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
show: props.show === true
};
}
toggle(show) {
let timeout = 500;
if (this.props.randomTimeout) {
timeout = random();
}
setTimeout(() => {
this.setState({
show: show
})
}, timeout)
}
handleFocus() {
this.toggle(true);
}
handleBlur() {
this.toggle(false);
}
render() {
const btnId = `${this.props.id}-input`;
const contentId = `${this.props.id}-content`;
const classNames = ["alert"];
if (this.state.show === true) {
classNames.push("alert-success");
}
return e("div", {className: "card focusable"}, [
e("div", { className: "card-header"}, [
e("div", { classNames: "form-group" }, [
e("input", {
id: btnId,
className: "form-control",
onFocus: this.handleFocus.bind(this),
onBlur: this.handleBlur.bind(this)
})
])
]),
e("div", { className: "card-body"}, [
e("div", { id: contentId, className: classNames.join(" ")}, [
e("p", null, [
"Lorem ipsum dolor sit amet."
])
])
])
]);
}
}

View File

@@ -1,6 +1,7 @@
import Hoverable from "./hoverable.js"; import Hoverable from "./hoverable.js";
import Clickable from "./clickable.js"; import Clickable from "./clickable.js";
import Appearable from "./appearable.js"; import Appearable from "./appearable.js";
import Focusable from "./focusable.js";
const e = React.createElement; const e = React.createElement;
@@ -73,6 +74,15 @@ export default class EventsPage extends React.Component {
useStyle: true, useStyle: true,
}) })
]), ]),
]),
e("div", { className: "row" }, [
e("div", { className: "col-lg-4"}, [
e(Focusable, {
id: "focus",
appear: false,
title: "Focusable"
})
]),
]) ])
]) ])
} }

View File

@@ -0,0 +1,8 @@
LET url = @dynamic + "/#/events"
LET page = DOCUMENT(url, true)
FOCUS(page, "#focus-input")
WAIT_CLASS(page, "#focus-content", "alert-success")
RETURN ""

View File

@@ -0,0 +1,10 @@
LET url = @dynamic + "/#/events"
LET page = DOCUMENT(url, true)
LET input = ELEMENT(page, "#focus-input")
FOCUS(input)
WAIT_CLASS(page, "#focus-content", "alert-success")
RETURN ""

View File

@@ -345,6 +345,10 @@ func (doc *HTMLDocument) SelectBySelector(ctx context.Context, selector values.S
return doc.input.SelectBySelector(ctx, doc.element.id.nodeID, selector, value) return doc.input.SelectBySelector(ctx, doc.element.id.nodeID, selector, value)
} }
func (doc *HTMLDocument) FocusBySelector(ctx context.Context, selector values.String) error {
return doc.input.FocusBySelector(ctx, doc.element.id.nodeID, selector)
}
func (doc *HTMLDocument) MoveMouseBySelector(ctx context.Context, selector values.String) error { func (doc *HTMLDocument) MoveMouseBySelector(ctx context.Context, selector values.String) error {
return doc.input.MoveMouseBySelector(ctx, doc.element.id.nodeID, selector) return doc.input.MoveMouseBySelector(ctx, doc.element.id.nodeID, selector)
} }

View File

@@ -971,6 +971,10 @@ func (el *HTMLElement) ScrollIntoView(ctx context.Context) error {
return el.input.ScrollIntoView(ctx, el.id.objectID) return el.input.ScrollIntoView(ctx, el.id.objectID)
} }
func (el *HTMLElement) Focus(ctx context.Context) error {
return el.input.Focus(ctx, el.id.objectID)
}
func (el *HTMLElement) Hover(ctx context.Context) error { func (el *HTMLElement) Hover(ctx context.Context) error {
return el.input.MoveMouse(ctx, el.id.objectID) return el.input.MoveMouse(ctx, el.id.objectID)
} }

View File

@@ -247,6 +247,10 @@ func (doc *HTMLDocument) ScrollByXY(_ context.Context, _, _ values.Float) error
return core.ErrNotSupported return core.ErrNotSupported
} }
func (doc *HTMLDocument) FocusBySelector(_ context.Context, _ values.String) error {
return core.ErrNotSupported
}
func (doc *HTMLDocument) MoveMouseBySelector(_ context.Context, _ values.String) error { func (doc *HTMLDocument) MoveMouseBySelector(_ context.Context, _ values.String) error {
return core.ErrNotSupported return core.ErrNotSupported
} }

View File

@@ -505,6 +505,10 @@ func (el *HTMLElement) ScrollIntoView(_ context.Context) error {
return core.ErrNotSupported return core.ErrNotSupported
} }
func (el *HTMLElement) Focus(_ context.Context) error {
return core.ErrNotSupported
}
func (el *HTMLElement) Hover(_ context.Context) error { func (el *HTMLElement) Hover(_ context.Context) error {
return core.ErrNotSupported return core.ErrNotSupported
} }

View File

@@ -101,6 +101,8 @@ type (
ScrollIntoView(ctx context.Context) error ScrollIntoView(ctx context.Context) error
Focus(ctx context.Context) error
Hover(ctx context.Context) error Hover(ctx context.Context) error
WaitForAttribute(ctx context.Context, name values.String, value core.Value, when WaitEvent) error WaitForAttribute(ctx context.Context, name values.String, value core.Value, when WaitEvent) error
@@ -141,6 +143,8 @@ type (
ScrollByXY(ctx context.Context, x, y values.Float) error ScrollByXY(ctx context.Context, x, y values.Float) error
FocusBySelector(ctx context.Context, selector values.String) error
MoveMouseByXY(ctx context.Context, x, y values.Float) error MoveMouseByXY(ctx context.Context, x, y values.Float) error
MoveMouseBySelector(ctx context.Context, selector values.String) error MoveMouseBySelector(ctx context.Context, selector values.String) error

38
pkg/stdlib/html/focus.go Normal file
View File

@@ -0,0 +1,38 @@
package html
import (
"context"
"github.com/MontFerret/ferret/pkg/drivers"
"github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values"
)
// FOCUS Calls focus on the element.
// @param target (HTMLPage | HTMLDocument | HTMLElement) - Target node.
// @param selector (String, optional) - Optional CSS selector. Required when target is HTMLPage or HTMLDocument.
func Focus(ctx context.Context, args ...core.Value) (core.Value, error) {
err := core.ValidateArgs(args, 1, 2)
if err != nil {
return values.None, err
}
// Document with selector
if len(args) == 2 {
doc, err := drivers.ToDocument(args[0])
if err != nil {
return values.None, err
}
return values.None, doc.FocusBySelector(ctx, values.ToString(args[1]))
}
el, err := drivers.ToElement(args[0])
if err != nil {
return values.None, err
}
return values.None, el.Focus(ctx)
}

View File

@@ -28,6 +28,7 @@ func RegisterLib(ns core.Namespace) error {
"ELEMENT_EXISTS": ElementExists, "ELEMENT_EXISTS": ElementExists,
"ELEMENTS": Elements, "ELEMENTS": Elements,
"ELEMENTS_COUNT": ElementsCount, "ELEMENTS_COUNT": ElementsCount,
"FOCUS": Focus,
"HOVER": Hover, "HOVER": Hover,
"INNER_HTML": GetInnerHTML, "INNER_HTML": GetInnerHTML,
"INNER_HTML_SET": SetInnerHTML, "INNER_HTML_SET": SetInnerHTML,