diff --git a/e2e/tests/dynamic/element/blur/blur.fql b/e2e/tests/dynamic/element/blur/blur.fql new file mode 100644 index 00000000..4b35c02a --- /dev/null +++ b/e2e/tests/dynamic/element/blur/blur.fql @@ -0,0 +1,14 @@ +LET url = @dynamic + "/#/events" +LET page = DOCUMENT(url, true) + +LET input = ELEMENT(page, "#focus-input") + +FOCUS(input) + +WAIT_CLASS(page, "#focus-content", "alert-success") + +BLUR(input) + +WAIT_NO_CLASS(page, "#focus-content", "alert-success") + +RETURN "" \ No newline at end of file diff --git a/e2e/tests/dynamic/element/blur/blur_by_selector.fql b/e2e/tests/dynamic/element/blur/blur_by_selector.fql new file mode 100644 index 00000000..e48e46fd --- /dev/null +++ b/e2e/tests/dynamic/element/blur/blur_by_selector.fql @@ -0,0 +1,12 @@ +LET url = @dynamic + "/#/events" +LET page = DOCUMENT(url, true) + +FOCUS(page, "#focus-input") + +WAIT_CLASS(page, "#focus-content", "alert-success") + +BLUR(page, "#focus-input") + +WAIT_NO_CLASS(page, "#focus-content", "alert-success") + +RETURN "" \ No newline at end of file diff --git a/e2e/tests/dynamic/element/focus/focus_ by_selector.fql b/e2e/tests/dynamic/element/focus/focus_ by_selector.fql new file mode 100644 index 00000000..295417d9 --- /dev/null +++ b/e2e/tests/dynamic/element/focus/focus_ by_selector.fql @@ -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 "" \ No newline at end of file diff --git a/e2e/tests/el_hover_d.fql b/e2e/tests/dynamic/element/hover/hover.fql similarity index 100% rename from e2e/tests/el_hover_d.fql rename to e2e/tests/dynamic/element/hover/hover.fql diff --git a/e2e/tests/doc_hover_d.fql b/e2e/tests/dynamic/element/hover/hover_by_selector.fql similarity index 100% rename from e2e/tests/doc_hover_d.fql rename to e2e/tests/dynamic/element/hover/hover_by_selector.fql diff --git a/pkg/drivers/cdp/element.go b/pkg/drivers/cdp/element.go index d0e38290..22883959 100644 --- a/pkg/drivers/cdp/element.go +++ b/pkg/drivers/cdp/element.go @@ -1086,6 +1086,14 @@ func (el *HTMLElement) FocusBySelector(ctx context.Context, selector values.Stri return el.input.FocusBySelector(ctx, el.id.nodeID, selector.String()) } +func (el *HTMLElement) Blur(ctx context.Context) error { + return el.input.Blur(ctx, el.id.objectID) +} + +func (el *HTMLElement) BlurBySelector(ctx context.Context, selector values.String) error { + return el.input.BlurBySelector(ctx, el.id.objectID, selector.String()) +} + func (el *HTMLElement) Hover(ctx context.Context) error { return el.input.MoveMouse(ctx, el.id.objectID) } diff --git a/pkg/drivers/cdp/input/manager.go b/pkg/drivers/cdp/input/manager.go index 1379cb7f..39a483e5 100644 --- a/pkg/drivers/cdp/input/manager.go +++ b/pkg/drivers/cdp/input/manager.go @@ -107,6 +107,18 @@ func (m *Manager) FocusBySelector(ctx context.Context, parentNodeID dom.NodeID, return m.client.DOM.Focus(ctx, dom.NewFocusArgs().SetNodeID(found.NodeID)) } +func (m *Manager) Blur(ctx context.Context, objectID runtime.RemoteObjectID) error { + return m.exec.EvalWithArguments(ctx, templates.Blur(), runtime.CallArgument{ + ObjectID: &objectID, + }) +} + +func (m *Manager) BlurBySelector(ctx context.Context, parentObjectID runtime.RemoteObjectID, selector string) error { + return m.exec.EvalWithArguments(ctx, templates.BlurBySelector(selector), runtime.CallArgument{ + ObjectID: &parentObjectID, + }) +} + func (m *Manager) MoveMouse(ctx context.Context, objectID runtime.RemoteObjectID) error { if err := m.ScrollIntoView(ctx, objectID); err != nil { return err diff --git a/pkg/drivers/cdp/templates/blur.go b/pkg/drivers/cdp/templates/blur.go new file mode 100644 index 00000000..8f22294b --- /dev/null +++ b/pkg/drivers/cdp/templates/blur.go @@ -0,0 +1,28 @@ +package templates + +import ( + "fmt" + "github.com/MontFerret/ferret/pkg/drivers" +) + +func Blur() string { + return ` + (el) => { + el.blur() + } + ` +} + +func BlurBySelector(selector string) string { + return fmt.Sprintf(` + (parent) => { + const el = parent.querySelector('%s'); + + if (el == null) { + throw new Error('%s') + } + + el.blur(); + } +`, selector, drivers.ErrNotFound) +} diff --git a/pkg/drivers/http/element.go b/pkg/drivers/http/element.go index ad0db7f7..2f7e252d 100644 --- a/pkg/drivers/http/element.go +++ b/pkg/drivers/http/element.go @@ -537,6 +537,14 @@ func (el *HTMLElement) FocusBySelector(_ context.Context, _ values.String) error return core.ErrNotSupported } +func (el *HTMLElement) Blur(_ context.Context) error { + return core.ErrNotSupported +} + +func (el *HTMLElement) BlurBySelector(_ context.Context, _ values.String) error { + return core.ErrNotSupported +} + func (el *HTMLElement) Hover(_ context.Context) error { return core.ErrNotSupported } diff --git a/pkg/drivers/value.go b/pkg/drivers/value.go index 84e6ec2f..cc4e42b0 100644 --- a/pkg/drivers/value.go +++ b/pkg/drivers/value.go @@ -117,6 +117,10 @@ type ( FocusBySelector(ctx context.Context, selector values.String) error + Blur(ctx context.Context) error + + BlurBySelector(ctx context.Context, selector values.String) error + Hover(ctx context.Context) error HoverBySelector(ctx context.Context, selector values.String) error diff --git a/pkg/stdlib/html/blur.go b/pkg/stdlib/html/blur.go new file mode 100644 index 00000000..8569bcf9 --- /dev/null +++ b/pkg/stdlib/html/blur.go @@ -0,0 +1,32 @@ +package html + +import ( + "context" + "github.com/MontFerret/ferret/pkg/drivers" + "github.com/MontFerret/ferret/pkg/runtime/values" + + "github.com/MontFerret/ferret/pkg/runtime/core" +) + +// BLUR Calls blur on the element. +// @param target (HTMLPage | HTMLDocument | HTMLElement) - Target node. +// @param selector (String, optional) - Optional CSS selector. +func Blur(ctx context.Context, args ...core.Value) (core.Value, error) { + err := core.ValidateArgs(args, 1, 2) + + if err != nil { + return values.None, err + } + + el, err := drivers.ToElement(args[0]) + + if err != nil { + return values.None, err + } + + if len(args) == 1 { + return values.None, el.Blur(ctx) + } + + return values.None, el.BlurBySelector(ctx, values.ToString(args[1])) +} diff --git a/pkg/stdlib/html/focus.go b/pkg/stdlib/html/focus.go index 79bdcdd9..1cdc8487 100644 --- a/pkg/stdlib/html/focus.go +++ b/pkg/stdlib/html/focus.go @@ -8,9 +8,9 @@ import ( "github.com/MontFerret/ferret/pkg/runtime/values" ) -// FOCUS Calls focus on the element. +// FOCUS Sets 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. +// @param selector (String, optional) - Optional CSS selector. func Focus(ctx context.Context, args ...core.Value) (core.Value, error) { err := core.ValidateArgs(args, 1, 2) diff --git a/pkg/stdlib/html/lib.go b/pkg/stdlib/html/lib.go index 1dd6d83c..39bcc1cf 100644 --- a/pkg/stdlib/html/lib.go +++ b/pkg/stdlib/html/lib.go @@ -15,6 +15,7 @@ func RegisterLib(ns core.Namespace) error { "ATTR_GET": AttributeGet, "ATTR_REMOVE": AttributeRemove, "ATTR_SET": AttributeSet, + "BLUR": Blur, "COOKIE_DEL": CookieDel, "COOKIE_GET": CookieGet, "COOKIE_SET": CookieSet,