From 533f868b8511404d52a296964354698d6cc942e6 Mon Sep 17 00:00:00 2001 From: Tim Voronov Date: Thu, 27 Sep 2018 22:03:35 -0400 Subject: [PATCH] Added new methods --- pkg/stdlib/html/actions.go | 31 +++++ pkg/stdlib/html/data.go | 132 +++++++++++++++++++ pkg/stdlib/html/driver/dynamic/document.go | 140 +++++++++++++++++++++ pkg/stdlib/html/lib.go | 5 + 4 files changed, 308 insertions(+) create mode 100644 pkg/stdlib/html/data.go diff --git a/pkg/stdlib/html/actions.go b/pkg/stdlib/html/actions.go index 31f736a8..707c0a21 100644 --- a/pkg/stdlib/html/actions.go +++ b/pkg/stdlib/html/actions.go @@ -57,6 +57,37 @@ func Click(_ context.Context, args ...core.Value) (core.Value, error) { return doc.ClickBySelector(values.NewString(selector)) } +/* + * Dispatches click event on all matched element + * @param source (Document) - Document. + * @param selector (String) - Selector. + * @returns (Boolean) - Returns true if matched at least one element. + */ +func ClickAll(_ context.Context, args ...core.Value) (core.Value, error) { + err := core.ValidateArgs(args, 2, 2) + + if err != nil { + return values.False, err + } + + arg1 := args[0] + selector := args[1].String() + + err = core.ValidateType(arg1, core.HtmlDocumentType) + + if err != nil { + return values.None, err + } + + doc, ok := arg1.(*dynamic.HtmlDocument) + + if !ok { + return values.False, core.Error(core.ErrInvalidType, "expected dynamic document") + } + + return doc.ClickBySelectorAll(values.NewString(selector)) +} + /* * Navigates a document to a new resource. * The operation blocks the execution until the page gets loaded. diff --git a/pkg/stdlib/html/data.go b/pkg/stdlib/html/data.go new file mode 100644 index 00000000..f580be82 --- /dev/null +++ b/pkg/stdlib/html/data.go @@ -0,0 +1,132 @@ +package html + +import ( + "context" + "github.com/MontFerret/ferret/pkg/runtime/core" + "github.com/MontFerret/ferret/pkg/runtime/values" + "github.com/MontFerret/ferret/pkg/stdlib/html/driver/dynamic" +) + +/* + * Returns inner html of a matched element + * @param doc (Document) - Document + * @param selector (String) - Selector + * @returns str (String) - String value of inner html. + */ +func InnerHtml(_ context.Context, args ...core.Value) (core.Value, error) { + err := core.ValidateArgs(args, 2, 2) + + if err != nil { + return values.EmptyString, err + } + + arg1 := args[0] + selector := args[1].String() + + err = core.ValidateType(arg1, core.HtmlDocumentType) + + if err != nil { + return values.None, err + } + + doc, ok := arg1.(*dynamic.HtmlDocument) + + if !ok { + return values.EmptyString, core.Error(core.ErrInvalidType, "expected dynamic document") + } + + return doc.InnerHtmlBySelector(values.NewString(selector)) +} + +/* + * Returns inner html of all matched elements. + * @param doc (Document) - Document + * @param selector (String) - Selector + * @returns array (Array) - Array of string values. + */ +func InnerHtmlAll(_ context.Context, args ...core.Value) (core.Value, error) { + err := core.ValidateArgs(args, 2, 2) + + if err != nil { + return values.EmptyString, err + } + + arg1 := args[0] + selector := args[1].String() + + err = core.ValidateType(arg1, core.HtmlDocumentType) + + if err != nil { + return values.None, err + } + + doc, ok := arg1.(*dynamic.HtmlDocument) + + if !ok { + return values.EmptyString, core.Error(core.ErrInvalidType, "expected dynamic document") + } + + return doc.InnerHtmlBySelectorAll(values.NewString(selector)) +} + +/* + * Returns inner text of a matched element + * @param doc (Document) - Document + * @param selector (String) - Selector + * @returns str (String) - String value of inner text. + */ +func InnerText(_ context.Context, args ...core.Value) (core.Value, error) { + err := core.ValidateArgs(args, 2, 2) + + if err != nil { + return values.EmptyString, err + } + + arg1 := args[0] + selector := args[1].String() + + err = core.ValidateType(arg1, core.HtmlDocumentType) + + if err != nil { + return values.None, err + } + + doc, ok := arg1.(*dynamic.HtmlDocument) + + if !ok { + return values.EmptyString, core.Error(core.ErrInvalidType, "expected dynamic document") + } + + return doc.InnerHtmlBySelector(values.NewString(selector)) +} + +/* + * Returns inner text of all matched elements. + * @param doc (Document) - Document + * @param selector (String) - Selector + * @returns array (Array) - Array of string values. + */ +func InnerTextAll(_ context.Context, args ...core.Value) (core.Value, error) { + err := core.ValidateArgs(args, 2, 2) + + if err != nil { + return values.EmptyString, err + } + + arg1 := args[0] + selector := args[1].String() + + err = core.ValidateType(arg1, core.HtmlDocumentType) + + if err != nil { + return values.None, err + } + + doc, ok := arg1.(*dynamic.HtmlDocument) + + if !ok { + return values.EmptyString, core.Error(core.ErrInvalidType, "expected dynamic document") + } + + return doc.InnerHtmlBySelectorAll(values.NewString(selector)) +} diff --git a/pkg/stdlib/html/driver/dynamic/document.go b/pkg/stdlib/html/driver/dynamic/document.go index 4865fbe6..cae40ff2 100644 --- a/pkg/stdlib/html/driver/dynamic/document.go +++ b/pkg/stdlib/html/driver/dynamic/document.go @@ -323,6 +323,114 @@ func (doc *HtmlDocument) Url() core.Value { return doc.url } +func (doc *HtmlDocument) InnerHtmlBySelector(selector values.String) (values.String, error) { + res, err := eval.Eval( + doc.client, + fmt.Sprintf(` + var el = document.querySelector(%s); + + if (el == null) { + return ""; + } + + return el.innerHtml; + `, eval.ParamString(selector.String())), + true, + false, + ) + + if err != nil { + return values.EmptyString, err + } + + if res.Type() == core.StringType { + return res.(values.String), nil + } + + return values.EmptyString, nil +} + +func (doc *HtmlDocument) InnerHtmlBySelectorAll(selector values.String) (*values.Array, error) { + res, err := eval.Eval( + doc.client, + fmt.Sprintf(` + var elements = document.querySelectorAll(%s); + + if (elements == null) { + return []; + } + + return elements.map(i => i.innerHtml); + `, eval.ParamString(selector.String())), + true, + false, + ) + + if err != nil { + return values.NewArray(0), err + } + + if res.Type() == core.ArrayType { + return res.(*values.Array), nil + } + + return values.NewArray(0), nil +} + +func (doc *HtmlDocument) InnerTextBySelector(selector values.String) (values.String, error) { + res, err := eval.Eval( + doc.client, + fmt.Sprintf(` + var el = document.querySelector(%s); + + if (el == null) { + return ""; + } + + return el.innerText; + `, eval.ParamString(selector.String())), + true, + false, + ) + + if err != nil { + return values.EmptyString, err + } + + if res.Type() == core.StringType { + return res.(values.String), nil + } + + return values.EmptyString, nil +} + +func (doc *HtmlDocument) InnerTextBySelectorAll(selector values.String) (*values.Array, error) { + res, err := eval.Eval( + doc.client, + fmt.Sprintf(` + var elements = document.querySelectorAll(%s); + + if (elements == null) { + return []; + } + + return elements.map(i => i.innerText); + `, eval.ParamString(selector.String())), + true, + false, + ) + + if err != nil { + return values.NewArray(0), err + } + + if res.Type() == core.ArrayType { + return res.(*values.Array), nil + } + + return values.NewArray(0), nil +} + func (doc *HtmlDocument) ClickBySelector(selector values.String) (values.Boolean, error) { res, err := eval.Eval( doc.client, @@ -353,6 +461,38 @@ func (doc *HtmlDocument) ClickBySelector(selector values.String) (values.Boolean return values.False, nil } +func (doc *HtmlDocument) ClickBySelectorAll(selector values.String) (values.Boolean, error) { + res, err := eval.Eval( + doc.client, + fmt.Sprintf(` + var elements = document.querySelectorAll(%s); + + if (elements == null) { + return false; + } + + elements.forEach((el) => { + var evt = new window.MouseEvent('click', { bubbles: true }); + el.dispatchEvent(evt); + }); + + return true; + `, eval.ParamString(selector.String())), + true, + false, + ) + + if err != nil { + return values.False, err + } + + if res.Type() == core.BooleanType { + return res.(values.Boolean), nil + } + + return values.False, nil +} + func (doc *HtmlDocument) InputBySelector(selector values.String, value core.Value) (values.Boolean, error) { res, err := eval.Eval( doc.client, diff --git a/pkg/stdlib/html/lib.go b/pkg/stdlib/html/lib.go index f6b4d6b9..6321c098 100644 --- a/pkg/stdlib/html/lib.go +++ b/pkg/stdlib/html/lib.go @@ -11,7 +11,12 @@ func NewLib() map[string]core.Function { "WAIT_ELEMENT": WaitElement, "WAIT_NAVIGATION": WaitNavigation, "CLICK": Click, + "CLICK_ALL": ClickAll, "NAVIGATE": Navigate, "INPUT": Input, + "INNER_HTML": InnerHtml, + "INNER_HTML_ALL": InnerHtmlAll, + "INNER_TEXT": InnerText, + "INNER_TEXT_ALL": InnerTextAll, } }