mirror of
https://github.com/MontFerret/ferret.git
synced 2024-12-12 11:15:14 +02:00
Added possibility to use FOR loop in ternary expression
This commit is contained in:
parent
ef29241aa6
commit
8b2e210317
24
docs/examples/input.fql
Normal file
24
docs/examples/input.fql
Normal file
@ -0,0 +1,24 @@
|
||||
LET g = DOCUMENT("https://www.google.com/", true)
|
||||
LET inputBox = ELEMENT(g, 'input[name="q"]')
|
||||
|
||||
INPUT(inputBox, "ferrer")
|
||||
|
||||
LET searchBtn = ELEMENT(g, 'input[name="btnK"]')
|
||||
|
||||
CLICK(searchBtn)
|
||||
|
||||
WAIT_NAVIGATION(g)
|
||||
|
||||
LET result = ELEMENTS(g, '.g')
|
||||
|
||||
LOG(result ? 'element' : 'no element')
|
||||
|
||||
RETURN result ? (
|
||||
FOR result IN ELEMENTS(g, '.g')
|
||||
LOG('iterate')
|
||||
RETURN {
|
||||
title: ELEMENT(result, 'h3 > a'),
|
||||
description: ELEMENT(result, '.st'),
|
||||
url: ELEMENT(result, 'cite')
|
||||
}
|
||||
) : 'no results'
|
@ -90,3 +90,13 @@ func (c *FqlCompiler) Compile(query string) (program *runtime.Program, err error
|
||||
|
||||
return program, err
|
||||
}
|
||||
|
||||
func (c *FqlCompiler) CompileP(query string) *runtime.Program {
|
||||
program, err := c.Compile(query)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return program
|
||||
}
|
||||
|
@ -1602,6 +1602,92 @@ func TestInOperator(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestForTernaryExpression(t *testing.T) {
|
||||
Convey("RETURN foo ? TRUE : (FOR i IN 1..5 RETURN i*2)", t, func() {
|
||||
c := compiler.New()
|
||||
|
||||
out1, err := c.CompileP(`
|
||||
LET foo = FALSE
|
||||
RETURN foo ? TRUE : (FOR i IN 1..5 RETURN i*2)
|
||||
`).Run(context.Background())
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(string(out1), ShouldEqual, `[2,4,6,8,10]`)
|
||||
|
||||
out2, err := c.CompileP(`
|
||||
LET foo = TRUE
|
||||
RETURN foo ? TRUE : (FOR i IN 1..5 RETURN i*2)
|
||||
`).Run(context.Background())
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(string(out2), ShouldEqual, `true`)
|
||||
})
|
||||
|
||||
Convey("RETURN foo ? (FOR i IN 1..5 RETURN i) : (FOR i IN 1..5 RETURN i*2)", t, func() {
|
||||
c := compiler.New()
|
||||
|
||||
out1, err := c.CompileP(`
|
||||
LET foo = FALSE
|
||||
RETURN foo ? (FOR i IN 1..5 RETURN i) : (FOR i IN 1..5 RETURN i*2)
|
||||
`).Run(context.Background())
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(string(out1), ShouldEqual, `[2,4,6,8,10]`)
|
||||
|
||||
out2, err := c.CompileP(`
|
||||
LET foo = TRUE
|
||||
RETURN foo ? (FOR i IN 1..5 RETURN i) : (FOR i IN 1..5 RETURN i*2)
|
||||
`).Run(context.Background())
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(string(out2), ShouldEqual, `[1,2,3,4,5]`)
|
||||
})
|
||||
|
||||
Convey("LET res = foo ? TRUE : (FOR i IN 1..5 RETURN i*2)", t, func() {
|
||||
c := compiler.New()
|
||||
|
||||
out1, err := c.CompileP(`
|
||||
LET foo = FALSE
|
||||
LET res = foo ? TRUE : (FOR i IN 1..5 RETURN i*2)
|
||||
RETURN res
|
||||
`).Run(context.Background())
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(string(out1), ShouldEqual, `[2,4,6,8,10]`)
|
||||
|
||||
out2, err := c.CompileP(`
|
||||
LET foo = TRUE
|
||||
LET res = foo ? TRUE : (FOR i IN 1..5 RETURN i*2)
|
||||
RETURN res
|
||||
`).Run(context.Background())
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(string(out2), ShouldEqual, `true`)
|
||||
})
|
||||
|
||||
Convey("LET res = foo ? (FOR i IN 1..5 RETURN i) : (FOR i IN 1..5 RETURN i*2)", t, func() {
|
||||
c := compiler.New()
|
||||
|
||||
out1, err := c.CompileP(`
|
||||
LET foo = FALSE
|
||||
LET res = foo ? (FOR i IN 1..5 RETURN i) : (FOR i IN 1..5 RETURN i*2)
|
||||
RETURN res
|
||||
`).Run(context.Background())
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(string(out1), ShouldEqual, `[2,4,6,8,10]`)
|
||||
|
||||
out2, err := c.CompileP(`
|
||||
LET foo = TRUE
|
||||
LET res = foo ? (FOR i IN 1..5 RETURN i) : (FOR i IN 1..5 RETURN i*2)
|
||||
RETURN res
|
||||
`).Run(context.Background())
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(string(out2), ShouldEqual, `[1,2,3,4,5]`)
|
||||
})
|
||||
}
|
||||
|
||||
//func TestHtml(t *testing.T) {
|
||||
// Convey("Should load a document", t, func() {
|
||||
// c := compiler.New()
|
||||
|
@ -117,7 +117,13 @@ func (v *visitor) doVisitReturnExpression(ctx *fql.ReturnExpressionContext, scop
|
||||
}
|
||||
|
||||
exp = out
|
||||
} else {
|
||||
|
||||
return expressions.NewReturnExpression(v.getSourceMap(ctx), exp)
|
||||
}
|
||||
|
||||
forIn := ctx.ForExpression()
|
||||
|
||||
if forIn != nil {
|
||||
out, err := v.doVisitForExpression(ctx.ForExpression().(*fql.ForExpressionContext), scope.Fork())
|
||||
|
||||
if err != nil {
|
||||
@ -125,9 +131,23 @@ func (v *visitor) doVisitReturnExpression(ctx *fql.ReturnExpressionContext, scop
|
||||
}
|
||||
|
||||
exp = out
|
||||
|
||||
return expressions.NewReturnExpression(v.getSourceMap(ctx), exp)
|
||||
}
|
||||
|
||||
return expressions.NewReturnExpression(v.getSourceMap(ctx), exp)
|
||||
forInTernary := ctx.ForTernaryExpression()
|
||||
|
||||
if forInTernary != nil {
|
||||
out, err := v.doVisitForTernaryExpression(forInTernary.(*fql.ForTernaryExpressionContext), scope)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return expressions.NewReturnExpression(v.getSourceMap(ctx), out)
|
||||
}
|
||||
|
||||
return nil, ErrNotImplemented
|
||||
}
|
||||
|
||||
func (v *visitor) doVisitForExpression(ctx *fql.ForExpressionContext, scope *scope) (core.Expression, error) {
|
||||
@ -609,7 +629,9 @@ func (v *visitor) doVisitVariableDeclaration(ctx *fql.VariableDeclarationContext
|
||||
|
||||
if exp != nil {
|
||||
init, err = v.doVisitExpression(ctx.Expression().(*fql.ExpressionContext), scope)
|
||||
} else {
|
||||
}
|
||||
|
||||
if init == nil && err == nil {
|
||||
forIn := ctx.ForExpression()
|
||||
|
||||
if forIn != nil {
|
||||
@ -617,6 +639,14 @@ func (v *visitor) doVisitVariableDeclaration(ctx *fql.VariableDeclarationContext
|
||||
}
|
||||
}
|
||||
|
||||
if init == nil && err == nil {
|
||||
forTer := ctx.ForTernaryExpression()
|
||||
|
||||
if forTer != nil {
|
||||
init, err = v.doVisitForTernaryExpression(forTer.(*fql.ForTernaryExpressionContext), scope)
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -661,16 +691,22 @@ func (v *visitor) doVisitChildren(node antlr.RuleNode, scope *scope) ([]core.Exp
|
||||
return make([]core.Expression, 0, 0), nil
|
||||
}
|
||||
|
||||
result := make([]core.Expression, len(children))
|
||||
result := make([]core.Expression, 0, len(children))
|
||||
|
||||
for _, child := range children {
|
||||
_, ok := child.(antlr.TerminalNode)
|
||||
|
||||
if ok {
|
||||
continue
|
||||
}
|
||||
|
||||
for idx, child := range children {
|
||||
out, err := v.visit(child, scope)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result[idx] = out
|
||||
result = append(result, out)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
@ -794,24 +830,10 @@ func (v *visitor) doVisitExpression(ctx *fql.ExpressionContext, scope *scope) (c
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var test core.Expression
|
||||
var consequent core.Expression
|
||||
var alternate core.Expression
|
||||
|
||||
if len(exps) == 3 {
|
||||
test = exps[0]
|
||||
consequent = exps[1]
|
||||
alternate = exps[2]
|
||||
} else {
|
||||
test = exps[0]
|
||||
alternate = exps[1]
|
||||
}
|
||||
|
||||
return expressions.NewConditionExpression(
|
||||
return v.createTernaryOperator(
|
||||
v.getSourceMap(ctx),
|
||||
test,
|
||||
consequent,
|
||||
alternate,
|
||||
exps,
|
||||
scope,
|
||||
)
|
||||
}
|
||||
|
||||
@ -860,14 +882,6 @@ func (v *visitor) doVisitExpression(ctx *fql.ExpressionContext, scope *scope) (c
|
||||
return v.doVisitRangeOperator(rangeOp.(*fql.RangeOperatorContext), scope)
|
||||
}
|
||||
|
||||
seq := ctx.ExpressionSequence()
|
||||
|
||||
if seq != nil {
|
||||
// seq := seq.(*fql.ExpressionSequenceContext)
|
||||
|
||||
return nil, core.Error(ErrNotImplemented, "expression sequence")
|
||||
}
|
||||
|
||||
// TODO: Complete it
|
||||
return nil, ErrNotImplemented
|
||||
}
|
||||
@ -981,6 +995,42 @@ func (v *visitor) visit(node antlr.Tree, scope *scope) (core.Expression, error)
|
||||
return out, err
|
||||
}
|
||||
|
||||
func (v *visitor) doVisitForTernaryExpression(ctx *fql.ForTernaryExpressionContext, scope *scope) (*expressions.ConditionExpression, error) {
|
||||
exps, err := v.doVisitChildren(ctx, scope)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return v.createTernaryOperator(
|
||||
v.getSourceMap(ctx),
|
||||
exps,
|
||||
scope,
|
||||
)
|
||||
}
|
||||
|
||||
func (v *visitor) createTernaryOperator(src core.SourceMap, exps []core.Expression, scope *scope) (*expressions.ConditionExpression, error) {
|
||||
var test core.Expression
|
||||
var consequent core.Expression
|
||||
var alternate core.Expression
|
||||
|
||||
if len(exps) == 3 {
|
||||
test = exps[0]
|
||||
consequent = exps[1]
|
||||
alternate = exps[2]
|
||||
} else {
|
||||
test = exps[0]
|
||||
alternate = exps[1]
|
||||
}
|
||||
|
||||
return expressions.NewConditionExpression(
|
||||
src,
|
||||
test,
|
||||
consequent,
|
||||
alternate,
|
||||
)
|
||||
}
|
||||
|
||||
func (v *visitor) unexpectedToken(node antlr.Tree) error {
|
||||
name := "undefined"
|
||||
ctx, ok := node.(antlr.RuleContext)
|
||||
|
@ -23,6 +23,7 @@ bodyExpression
|
||||
returnExpression
|
||||
: Return (Distinct)? expression
|
||||
| Return (Distinct)? OpenParen forExpression CloseParen
|
||||
| Return forTernaryExpression
|
||||
;
|
||||
|
||||
forExpression
|
||||
@ -124,6 +125,7 @@ forExpressionReturn
|
||||
variableDeclaration
|
||||
: Let Identifier Assign expression
|
||||
| Let Identifier Assign OpenParen forExpression CloseParen
|
||||
| Let Identifier Assign forTernaryExpression
|
||||
;
|
||||
|
||||
variable
|
||||
@ -225,6 +227,12 @@ expression
|
||||
| noneLiteral
|
||||
;
|
||||
|
||||
forTernaryExpression
|
||||
: expression QuestionMark expression? Colon OpenParen forExpression CloseParen
|
||||
| expression QuestionMark OpenParen forExpression CloseParen Colon expression
|
||||
| expression QuestionMark OpenParen forExpression CloseParen Colon OpenParen forExpression CloseParen
|
||||
;
|
||||
|
||||
equalityOperator
|
||||
: Gt
|
||||
| Lt
|
||||
@ -249,7 +257,7 @@ mathOperator
|
||||
|
||||
unaryOperator
|
||||
: Not
|
||||
| Plus
|
||||
| Plus
|
||||
| Minus
|
||||
| Like
|
||||
;
|
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@ -288,6 +288,12 @@ func (s *BaseFqlParserListener) EnterExpression(ctx *ExpressionContext) {}
|
||||
// ExitExpression is called when production expression is exited.
|
||||
func (s *BaseFqlParserListener) ExitExpression(ctx *ExpressionContext) {}
|
||||
|
||||
// EnterForTernaryExpression is called when production forTernaryExpression is entered.
|
||||
func (s *BaseFqlParserListener) EnterForTernaryExpression(ctx *ForTernaryExpressionContext) {}
|
||||
|
||||
// ExitForTernaryExpression is called when production forTernaryExpression is exited.
|
||||
func (s *BaseFqlParserListener) ExitForTernaryExpression(ctx *ForTernaryExpressionContext) {}
|
||||
|
||||
// EnterEqualityOperator is called when production equalityOperator is entered.
|
||||
func (s *BaseFqlParserListener) EnterEqualityOperator(ctx *EqualityOperatorContext) {}
|
||||
|
||||
|
@ -183,6 +183,10 @@ func (v *BaseFqlParserVisitor) VisitExpression(ctx *ExpressionContext) interface
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseFqlParserVisitor) VisitForTernaryExpression(ctx *ForTernaryExpressionContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseFqlParserVisitor) VisitEqualityOperator(ctx *EqualityOperatorContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
@ -139,6 +139,9 @@ type FqlParserListener interface {
|
||||
// EnterExpression is called when entering the expression production.
|
||||
EnterExpression(c *ExpressionContext)
|
||||
|
||||
// EnterForTernaryExpression is called when entering the forTernaryExpression production.
|
||||
EnterForTernaryExpression(c *ForTernaryExpressionContext)
|
||||
|
||||
// EnterEqualityOperator is called when entering the equalityOperator production.
|
||||
EnterEqualityOperator(c *EqualityOperatorContext)
|
||||
|
||||
@ -283,6 +286,9 @@ type FqlParserListener interface {
|
||||
// ExitExpression is called when exiting the expression production.
|
||||
ExitExpression(c *ExpressionContext)
|
||||
|
||||
// ExitForTernaryExpression is called when exiting the forTernaryExpression production.
|
||||
ExitForTernaryExpression(c *ForTernaryExpressionContext)
|
||||
|
||||
// ExitEqualityOperator is called when exiting the equalityOperator production.
|
||||
ExitEqualityOperator(c *EqualityOperatorContext)
|
||||
|
||||
|
@ -139,6 +139,9 @@ type FqlParserVisitor interface {
|
||||
// Visit a parse tree produced by FqlParser#expression.
|
||||
VisitExpression(ctx *ExpressionContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by FqlParser#forTernaryExpression.
|
||||
VisitForTernaryExpression(ctx *ForTernaryExpressionContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by FqlParser#equalityOperator.
|
||||
VisitEqualityOperator(ctx *EqualityOperatorContext) interface{}
|
||||
|
||||
|
@ -40,3 +40,13 @@ func (p *Program) Run(ctx context.Context, setters ...Option) ([]byte, error) {
|
||||
|
||||
return out.MarshalJSON()
|
||||
}
|
||||
|
||||
func (p *Program) RunP(ctx context.Context, setters ...Option) []byte {
|
||||
out, err := p.Run(ctx, setters...)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
@ -67,6 +67,14 @@ func GetIn(from core.Value, byPath []core.Value) (core.Value, error) {
|
||||
result = el.GetChildNodes()
|
||||
case "length":
|
||||
result = el.Length()
|
||||
case "url":
|
||||
if result.Type() == core.HtmlDocumentType {
|
||||
doc, ok := result.(HtmlDocument)
|
||||
|
||||
if ok {
|
||||
result = doc.Url()
|
||||
}
|
||||
}
|
||||
default:
|
||||
result = None
|
||||
}
|
||||
|
@ -2,30 +2,38 @@ package values
|
||||
|
||||
import "github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
|
||||
type HtmlNode interface {
|
||||
core.Value
|
||||
type (
|
||||
HtmlNode interface {
|
||||
core.Value
|
||||
|
||||
NodeType() Int
|
||||
NodeType() Int
|
||||
|
||||
NodeName() String
|
||||
NodeName() String
|
||||
|
||||
Length() Int
|
||||
Length() Int
|
||||
|
||||
InnerText() String
|
||||
InnerText() String
|
||||
|
||||
InnerHtml() String
|
||||
InnerHtml() String
|
||||
|
||||
Value() core.Value
|
||||
Value() core.Value
|
||||
|
||||
GetAttributes() core.Value
|
||||
GetAttributes() core.Value
|
||||
|
||||
GetAttribute(name String) core.Value
|
||||
GetAttribute(name String) core.Value
|
||||
|
||||
GetChildNodes() core.Value
|
||||
GetChildNodes() core.Value
|
||||
|
||||
GetChildNode(idx Int) core.Value
|
||||
GetChildNode(idx Int) core.Value
|
||||
|
||||
QuerySelector(selector String) core.Value
|
||||
QuerySelector(selector String) core.Value
|
||||
|
||||
QuerySelectorAll(selector String) core.Value
|
||||
}
|
||||
QuerySelectorAll(selector String) core.Value
|
||||
}
|
||||
|
||||
HtmlDocument interface {
|
||||
HtmlNode
|
||||
|
||||
Url() core.Value
|
||||
}
|
||||
)
|
||||
|
@ -91,3 +91,32 @@ func Navigate(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
|
||||
return values.None, doc.Navigate(args[1].(values.String))
|
||||
}
|
||||
|
||||
func Input(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
err := core.ValidateArgs(args, 2, 3)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
// TYPE(el, "foobar")
|
||||
if len(args) == 2 {
|
||||
arg1 := args[0]
|
||||
|
||||
err := core.ValidateType(arg1, core.HtmlElementType)
|
||||
|
||||
if err != nil {
|
||||
return values.False, err
|
||||
}
|
||||
|
||||
el, ok := arg1.(*dynamic.HtmlElement)
|
||||
|
||||
if !ok {
|
||||
return values.False, core.Error(core.ErrInvalidType, "expected dynamic element")
|
||||
}
|
||||
|
||||
return values.None, el.Input(args[1], values.NewInt(100))
|
||||
}
|
||||
|
||||
return values.None, nil
|
||||
}
|
||||
|
@ -15,7 +15,6 @@ import (
|
||||
"github.com/mafredri/cdp/protocol/page"
|
||||
"github.com/mafredri/cdp/rpcc"
|
||||
"github.com/pkg/errors"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
@ -25,7 +24,7 @@ type HtmlDocument struct {
|
||||
conn *rpcc.Conn
|
||||
client *cdp.Client
|
||||
events *events.EventBroker
|
||||
url string
|
||||
url values.String
|
||||
element *HtmlElement
|
||||
}
|
||||
|
||||
@ -132,7 +131,7 @@ func NewHtmlDocument(
|
||||
doc.url = ""
|
||||
|
||||
if root.BaseURL != nil {
|
||||
doc.url = *root.BaseURL
|
||||
doc.url = values.NewString(*root.BaseURL)
|
||||
}
|
||||
|
||||
broker.AddEventListener("load", func(_ interface{}) {
|
||||
@ -154,7 +153,7 @@ func NewHtmlDocument(
|
||||
doc.url = ""
|
||||
|
||||
if updated.BaseURL != nil {
|
||||
doc.url = *updated.BaseURL
|
||||
doc.url = values.NewString(*updated.BaseURL)
|
||||
}
|
||||
})
|
||||
|
||||
@ -176,7 +175,7 @@ func (doc *HtmlDocument) String() string {
|
||||
doc.Lock()
|
||||
defer doc.Unlock()
|
||||
|
||||
return doc.url
|
||||
return doc.url.String()
|
||||
}
|
||||
|
||||
func (doc *HtmlDocument) Unwrap() interface{} {
|
||||
@ -213,7 +212,7 @@ func (doc *HtmlDocument) Compare(other core.Value) int {
|
||||
case core.HtmlDocumentType:
|
||||
other := other.(*HtmlDocument)
|
||||
|
||||
return strings.Compare(doc.url, other.url)
|
||||
return doc.url.Compare(other.url)
|
||||
default:
|
||||
if other.Type() > core.HtmlDocumentType {
|
||||
return -1
|
||||
@ -320,6 +319,10 @@ func (doc *HtmlDocument) QuerySelectorAll(selector values.String) core.Value {
|
||||
return doc.element.QuerySelectorAll(selector)
|
||||
}
|
||||
|
||||
func (doc *HtmlDocument) Url() core.Value {
|
||||
return doc.url
|
||||
}
|
||||
|
||||
func (doc *HtmlDocument) ClickBySelector(selector values.String) (values.Boolean, error) {
|
||||
res, err := eval.Eval(
|
||||
doc.client,
|
||||
|
@ -164,11 +164,17 @@ func (el *HtmlElement) MarshalJSON() ([]byte, error) {
|
||||
el.Lock()
|
||||
defer el.Unlock()
|
||||
|
||||
return json.Marshal(el.innerHtml)
|
||||
val, err := el.innerText.Value()
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return json.Marshal(val.String())
|
||||
}
|
||||
|
||||
func (el *HtmlElement) String() string {
|
||||
return el.value.String()
|
||||
return el.InnerHtml().String()
|
||||
}
|
||||
|
||||
func (el *HtmlElement) Compare(other core.Value) int {
|
||||
@ -372,6 +378,13 @@ func (el *HtmlElement) Click() (values.Boolean, error) {
|
||||
return events.DispatchEvent(ctx, el.client, el.id, "click")
|
||||
}
|
||||
|
||||
func (el *HtmlElement) Input(value core.Value, timeout values.Int) error {
|
||||
ctx, cancel := contextWithTimeout()
|
||||
defer cancel()
|
||||
|
||||
return el.client.DOM.SetAttributeValue(ctx, dom.NewSetAttributeValueArgs(el.id, "value", value.String()))
|
||||
}
|
||||
|
||||
func (el *HtmlElement) IsConnected() values.Boolean {
|
||||
el.Lock()
|
||||
defer el.Unlock()
|
||||
|
@ -2,12 +2,13 @@ package static
|
||||
|
||||
import (
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/PuerkitoBio/goquery"
|
||||
)
|
||||
|
||||
type HtmlDocument struct {
|
||||
*HtmlElement
|
||||
url string
|
||||
url values.String
|
||||
}
|
||||
|
||||
func NewHtmlDocument(
|
||||
@ -28,7 +29,7 @@ func NewHtmlDocument(
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &HtmlDocument{el, url}, nil
|
||||
return &HtmlDocument{el, values.NewString(url)}, nil
|
||||
}
|
||||
|
||||
func (el *HtmlDocument) Type() core.Type {
|
||||
@ -38,8 +39,9 @@ func (el *HtmlDocument) Type() core.Type {
|
||||
func (el *HtmlDocument) Compare(other core.Value) int {
|
||||
switch other.Type() {
|
||||
case core.HtmlDocumentType:
|
||||
// TODO: complete the comparison
|
||||
return -1
|
||||
otherDoc := other.(values.HtmlDocument)
|
||||
|
||||
return el.url.Compare(otherDoc.Url())
|
||||
default:
|
||||
if other.Type() > core.HtmlDocumentType {
|
||||
return -1
|
||||
@ -48,3 +50,7 @@ func (el *HtmlDocument) Compare(other core.Value) int {
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
func (el *HtmlDocument) Url() core.Value {
|
||||
return el.url
|
||||
}
|
||||
|
@ -24,13 +24,7 @@ func NewHtmlElement(node *goquery.Selection) (*HtmlElement, error) {
|
||||
}
|
||||
|
||||
func (el *HtmlElement) MarshalJSON() ([]byte, error) {
|
||||
html, err := el.selection.Html()
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return json.Marshal(html)
|
||||
return json.Marshal(el.InnerText().String())
|
||||
}
|
||||
|
||||
func (el *HtmlElement) Type() core.Type {
|
||||
@ -38,7 +32,7 @@ func (el *HtmlElement) Type() core.Type {
|
||||
}
|
||||
|
||||
func (el *HtmlElement) String() string {
|
||||
return el.selection.Text()
|
||||
return el.InnerHtml().String()
|
||||
}
|
||||
|
||||
func (el *HtmlElement) Compare(other core.Value) int {
|
||||
|
@ -12,5 +12,6 @@ func NewLib() map[string]core.Function {
|
||||
"WAIT_NAVIGATION": WaitNavigation,
|
||||
"CLICK": Click,
|
||||
"NAVIGATE": Navigate,
|
||||
"INPUT": Input,
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user