1
0
mirror of https://github.com/MontFerret/ferret.git synced 2024-12-14 11:23:02 +02:00

Added missed errors to HTMLElement interface (#375)

* Added missed errors to HTMLElement interface

* Fixed test suit
This commit is contained in:
Tim Voronov 2019-09-06 21:02:41 -04:00 committed by GitHub
parent 2d645434d8
commit c773509469
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 134 additions and 121 deletions

View File

@ -243,23 +243,23 @@ func (doc *HTMLDocument) GetNodeName() values.String {
return "#document"
}
func (doc *HTMLDocument) GetChildNodes(ctx context.Context) core.Value {
func (doc *HTMLDocument) GetChildNodes(ctx context.Context) (*values.Array, error) {
return doc.element.GetChildNodes(ctx)
}
func (doc *HTMLDocument) GetChildNode(ctx context.Context, idx values.Int) core.Value {
func (doc *HTMLDocument) GetChildNode(ctx context.Context, idx values.Int) (core.Value, error) {
return doc.element.GetChildNode(ctx, idx)
}
func (doc *HTMLDocument) QuerySelector(ctx context.Context, selector values.String) core.Value {
func (doc *HTMLDocument) QuerySelector(ctx context.Context, selector values.String) (core.Value, error) {
return doc.element.QuerySelector(ctx, selector)
}
func (doc *HTMLDocument) QuerySelectorAll(ctx context.Context, selector values.String) core.Value {
func (doc *HTMLDocument) QuerySelectorAll(ctx context.Context, selector values.String) (*values.Array, error) {
return doc.element.QuerySelectorAll(ctx, selector)
}
func (doc *HTMLDocument) CountBySelector(ctx context.Context, selector values.String) values.Int {
func (doc *HTMLDocument) CountBySelector(ctx context.Context, selector values.String) (values.Int, error) {
return doc.element.CountBySelector(ctx, selector)
}

View File

@ -264,28 +264,25 @@ func (el *HTMLElement) SetIn(ctx context.Context, path []core.Value, value core.
return common.SetInElement(ctx, el, path, value)
}
func (el *HTMLElement) GetValue(ctx context.Context) core.Value {
func (el *HTMLElement) GetValue(ctx context.Context) (core.Value, error) {
if el.IsDetached() {
return el.value
return values.None, drivers.ErrDetached
}
val, err := el.exec.ReadProperty(ctx, el.id.objectID, "value")
if err != nil {
el.logError(err).Msg("failed to get node value")
return el.value
return values.None, err
}
el.value = val
return val
return val, nil
}
func (el *HTMLElement) SetValue(ctx context.Context, value core.Value) error {
if el.IsDetached() {
// TODO: Return an error
return nil
return drivers.ErrDetached
}
return el.client.DOM.SetNodeValue(ctx, dom.NewSetNodeValueArgs(el.id.nodeID, value.String()))
@ -396,33 +393,33 @@ func (el *HTMLElement) RemoveStyle(ctx context.Context, names ...values.String)
return el.SetAttribute(ctx, "style", str)
}
func (el *HTMLElement) GetAttributes(ctx context.Context) *values.Object {
func (el *HTMLElement) GetAttributes(ctx context.Context) (*values.Object, error) {
val, err := el.attributes.Read(ctx)
if err != nil {
return values.NewObject()
return values.NewObject(), err
}
attrs := val.(*values.Object)
// returning shallow copy
return attrs.Copy().(*values.Object)
return attrs.Copy().(*values.Object), nil
}
func (el *HTMLElement) GetAttribute(ctx context.Context, name values.String) core.Value {
func (el *HTMLElement) GetAttribute(ctx context.Context, name values.String) (core.Value, error) {
attrs, err := el.attributes.Read(ctx)
if err != nil {
return values.None
return values.None, err
}
val, found := attrs.(*values.Object).Get(name)
if !found {
return values.None
return values.None, nil
}
return val
return val, nil
}
func (el *HTMLElement) SetAttributes(ctx context.Context, attrs *values.Object) error {
@ -459,79 +456,61 @@ func (el *HTMLElement) RemoveAttribute(ctx context.Context, names ...values.Stri
return nil
}
func (el *HTMLElement) GetChildNodes(ctx context.Context) core.Value {
func (el *HTMLElement) GetChildNodes(ctx context.Context) (*values.Array, error) {
val, err := el.loadedChildren.Read(ctx)
if err != nil {
return values.NewArray(0)
return values.NewArray(0), err
}
return val
return val.Copy().(*values.Array), nil
}
func (el *HTMLElement) GetChildNode(ctx context.Context, idx values.Int) core.Value {
func (el *HTMLElement) GetChildNode(ctx context.Context, idx values.Int) (core.Value, error) {
val, err := el.loadedChildren.Read(ctx)
if err != nil {
return values.None
return values.None, err
}
return val.(*values.Array).Get(idx)
return val.(*values.Array).Get(idx), nil
}
func (el *HTMLElement) QuerySelector(ctx context.Context, selector values.String) core.Value {
func (el *HTMLElement) QuerySelector(ctx context.Context, selector values.String) (core.Value, error) {
if el.IsDetached() {
return values.None
return values.None, drivers.ErrDetached
}
// TODO: Can we use RemoteObjectID or BackendID instead of NodeId?
selectorArgs := dom.NewQuerySelectorArgs(el.id.nodeID, selector.String())
found, err := el.client.DOM.QuerySelector(ctx, selectorArgs)
if err != nil {
el.logError(err).
Str("selector", selector.String()).
Msg("failed to retrieve a node by selector")
return values.None
return values.None, err
}
if found.NodeID == emptyNodeID {
el.logError(err).
Str("selector", selector.String()).
Msg("failed to find a node by selector. returned 0 NodeID")
return values.None
return values.None, nil
}
res, err := LoadHTMLElement(ctx, el.logger, el.client, el.events, el.input, el.exec, found.NodeID)
if err != nil {
el.logError(err).
Str("selector", selector.String()).
Msg("failed to load a child node by selector")
return values.None
return values.None, nil
}
return res
return res, nil
}
func (el *HTMLElement) QuerySelectorAll(ctx context.Context, selector values.String) core.Value {
func (el *HTMLElement) QuerySelectorAll(ctx context.Context, selector values.String) (*values.Array, error) {
if el.IsDetached() {
return values.NewArray(0)
return values.NewArray(0), drivers.ErrDetached
}
// TODO: Can we use RemoteObjectID or BackendID instead of NodeId?
selectorArgs := dom.NewQuerySelectorAllArgs(el.id.nodeID, selector.String())
res, err := el.client.DOM.QuerySelectorAll(ctx, selectorArgs)
if err != nil {
el.logError(err).
Str("selector", selector.String()).
Msg("failed to retrieve nodes by selector")
return values.None
return values.NewArray(0), err
}
arr := values.NewArray(len(res.NodeIDs))
@ -548,10 +527,6 @@ func (el *HTMLElement) QuerySelectorAll(ctx context.Context, selector values.Str
childEl, err := LoadHTMLElement(ctx, el.logger, el.client, el.events, el.input, el.exec, id)
if err != nil {
el.logError(err).
Str("selector", selector.String()).
Msg("failed to load nodes by selector")
// close elements that are already loaded, but won't be used because of the error
if arr.Length() > 0 {
arr.ForEach(func(e core.Value, _ int) bool {
@ -561,13 +536,13 @@ func (el *HTMLElement) QuerySelectorAll(ctx context.Context, selector values.Str
})
}
return values.None
return values.NewArray(0), err
}
arr.Push(childEl)
}
return arr
return arr, nil
}
func (el *HTMLElement) XPath(ctx context.Context, expression values.String) (result core.Value, err error) {
@ -939,24 +914,19 @@ func (el *HTMLElement) GetInnerHTMLBySelectorAll(ctx context.Context, selector v
return arr, nil
}
func (el *HTMLElement) CountBySelector(ctx context.Context, selector values.String) values.Int {
func (el *HTMLElement) CountBySelector(ctx context.Context, selector values.String) (values.Int, error) {
if el.IsDetached() {
return values.ZeroInt
return values.ZeroInt, drivers.ErrDetached
}
// TODO: Can we use RemoteObjectID or BackendID instead of NodeId?
selectorArgs := dom.NewQuerySelectorAllArgs(el.id.nodeID, selector.String())
res, err := el.client.DOM.QuerySelectorAll(ctx, selectorArgs)
if err != nil {
el.logError(err).
Str("selector", selector.String()).
Msg("failed to retrieve nodes by selector")
return values.ZeroInt
return values.ZeroInt, err
}
return values.NewInt(len(res.NodeIDs))
return values.NewInt(len(res.NodeIDs)), nil
}
func (el *HTMLElement) ExistsBySelector(ctx context.Context, selector values.String) (values.Boolean, error) {
@ -982,7 +952,11 @@ func (el *HTMLElement) ExistsBySelector(ctx context.Context, selector values.Str
func (el *HTMLElement) WaitForClass(ctx context.Context, class values.String, when drivers.WaitEvent) error {
task := events.NewWaitTask(
func(ctx2 context.Context) (core.Value, error) {
current := el.GetAttribute(ctx2, "class")
current, err := el.GetAttribute(ctx2, "class")
if err != nil {
return values.None, nil
}
if current.Type() != types.String {
return values.None, nil
@ -1034,7 +1008,7 @@ func (el *HTMLElement) WaitForAttribute(
when drivers.WaitEvent,
) error {
task := events.NewValueWaitTask(when, value, func(ctx context.Context) (core.Value, error) {
return el.GetAttribute(ctx, name), nil
return el.GetAttribute(ctx, name)
}, events.DefaultPolling)
_, err := task.Run(ctx)
@ -1200,7 +1174,11 @@ func (el *HTMLElement) loadChildren(ctx context.Context) (core.Value, error) {
}
func (el *HTMLElement) parseStyle(ctx context.Context) (core.Value, error) {
value := el.GetAttribute(ctx, "style")
value, err := el.GetAttribute(ctx, "style")
if err != nil {
return values.None, err
}
if value == values.None {
return values.NewObject(), nil

View File

@ -111,7 +111,11 @@ func GetInDocument(ctx context.Context, doc drivers.HTMLDocument, path []core.Va
return GetInDocument(ctx, parent, path[1:])
case "body", "head":
out := doc.QuerySelector(ctx, segment)
out, err := doc.QuerySelector(ctx, segment)
if err != nil {
return values.None, err
}
if out == values.None {
return out, nil
@ -156,9 +160,13 @@ func GetInElement(ctx context.Context, el drivers.HTMLElement, path []core.Value
case "innerHTML":
return el.GetInnerHTML(ctx)
case "value":
return el.GetValue(ctx), nil
return el.GetValue(ctx)
case "attributes":
attrs := el.GetAttributes(ctx)
attrs, err := el.GetAttributes(ctx)
if err != nil {
return values.None, err
}
if len(path) == 1 {
return attrs, nil
@ -199,7 +207,7 @@ func GetInNode(ctx context.Context, node drivers.HTMLNode, path []core.Value) (c
if nt == drivers.HTMLElementType || nt == drivers.HTMLDocumentType {
re := node.(drivers.HTMLNode)
return re.GetChildNode(ctx, segment.(values.Int)), nil
return re.GetChildNode(ctx, values.ToInt(segment))
}
return values.GetIn(ctx, node, path[1:])
@ -214,7 +222,11 @@ func GetInNode(ctx context.Context, node drivers.HTMLNode, path []core.Value) (c
case "nodeName":
return node.GetNodeName(), nil
case "children":
children := node.GetChildNodes(ctx)
children, err := node.GetChildNodes(ctx)
if err != nil {
return values.None, err
}
if len(path) == 1 {
return children, nil

View File

@ -26,7 +26,11 @@ func NewIterator(
func (iterator *Iterator) Next(ctx context.Context) (value core.Value, key core.Value, err error) {
if iterator.node.Length() > iterator.pos {
idx := iterator.pos
val := iterator.node.GetChildNode(ctx, idx)
val, err := iterator.node.GetChildNode(ctx, idx)
if err != nil {
return values.None, values.None, err
}
iterator.pos++

View File

@ -49,7 +49,11 @@ func SetInElement(ctx context.Context, el drivers.HTMLElement, path []core.Value
return err
}
curr := el.GetAttributes(ctx)
curr, err := el.GetAttributes(ctx)
if err != nil {
return err
}
// remove all previous attributes
err = el.RemoveAttribute(ctx, curr.Keys()...)

View File

@ -149,23 +149,23 @@ func (doc *HTMLDocument) GetNodeName() values.String {
return "#document"
}
func (doc *HTMLDocument) GetChildNodes(ctx context.Context) core.Value {
func (doc *HTMLDocument) GetChildNodes(ctx context.Context) (*values.Array, error) {
return doc.element.GetChildNodes(ctx)
}
func (doc *HTMLDocument) GetChildNode(ctx context.Context, idx values.Int) core.Value {
func (doc *HTMLDocument) GetChildNode(ctx context.Context, idx values.Int) (core.Value, error) {
return doc.element.GetChildNode(ctx, idx)
}
func (doc *HTMLDocument) QuerySelector(ctx context.Context, selector values.String) core.Value {
func (doc *HTMLDocument) QuerySelector(ctx context.Context, selector values.String) (core.Value, error) {
return doc.element.QuerySelector(ctx, selector)
}
func (doc *HTMLDocument) QuerySelectorAll(ctx context.Context, selector values.String) core.Value {
func (doc *HTMLDocument) QuerySelectorAll(ctx context.Context, selector values.String) (*values.Array, error) {
return doc.element.QuerySelectorAll(ctx, selector)
}
func (doc *HTMLDocument) CountBySelector(ctx context.Context, selector values.String) values.Int {
func (doc *HTMLDocument) CountBySelector(ctx context.Context, selector values.String) (values.Int, error) {
return doc.element.CountBySelector(ctx, selector)
}

View File

@ -116,14 +116,14 @@ func (el *HTMLElement) Length() values.Int {
return el.children.Length()
}
func (el *HTMLElement) GetValue(_ context.Context) core.Value {
func (el *HTMLElement) GetValue(_ context.Context) (core.Value, error) {
val, ok := el.selection.Attr("value")
if ok {
return values.NewString(val)
return values.NewString(val), nil
}
return values.EmptyString
return values.EmptyString, nil
}
func (el *HTMLElement) SetValue(_ context.Context, value core.Value) error {
@ -242,16 +242,16 @@ func (el *HTMLElement) SetAttributes(ctx context.Context, attrs *values.Object)
return err
}
func (el *HTMLElement) GetAttributes(_ context.Context) *values.Object {
func (el *HTMLElement) GetAttributes(_ context.Context) (*values.Object, error) {
el.ensureAttrs()
return el.attrs.Copy().(*values.Object)
return el.attrs.Copy().(*values.Object), nil
}
func (el *HTMLElement) GetAttribute(_ context.Context, name values.String) core.Value {
func (el *HTMLElement) GetAttribute(_ context.Context, name values.String) (core.Value, error) {
el.ensureAttrs()
return el.attrs.MustGet(name)
return el.attrs.MustGet(name), nil
}
func (el *HTMLElement) SetAttribute(_ context.Context, name, value values.String) error {
@ -274,43 +274,43 @@ func (el *HTMLElement) RemoveAttribute(_ context.Context, name ...values.String)
return nil
}
func (el *HTMLElement) GetChildNodes(_ context.Context) core.Value {
func (el *HTMLElement) GetChildNodes(_ context.Context) (*values.Array, error) {
if el.children == nil {
el.children = el.parseChildren()
}
return el.children
return el.children.Copy().(*values.Array), nil
}
func (el *HTMLElement) GetChildNode(_ context.Context, idx values.Int) core.Value {
func (el *HTMLElement) GetChildNode(_ context.Context, idx values.Int) (core.Value, error) {
if el.children == nil {
el.children = el.parseChildren()
}
return el.children.Get(idx)
return el.children.Get(idx), nil
}
func (el *HTMLElement) QuerySelector(_ context.Context, selector values.String) core.Value {
func (el *HTMLElement) QuerySelector(_ context.Context, selector values.String) (core.Value, error) {
selection := el.selection.Find(selector.String())
if selection == nil {
return values.None
return values.None, nil
}
res, err := NewHTMLElement(selection)
if err != nil {
return values.None
return values.None, err
}
return res
return res, nil
}
func (el *HTMLElement) QuerySelectorAll(_ context.Context, selector values.String) core.Value {
func (el *HTMLElement) QuerySelectorAll(_ context.Context, selector values.String) (*values.Array, error) {
selection := el.selection.Find(selector.String())
if selection == nil {
return values.None
return values.NewArray(0), nil
}
arr := values.NewArray(selection.Length())
@ -323,7 +323,7 @@ func (el *HTMLElement) QuerySelectorAll(_ context.Context, selector values.Strin
}
})
return arr
return arr, nil
}
func (el *HTMLElement) XPath(_ context.Context, expression values.String) (core.Value, error) {
@ -457,14 +457,14 @@ func (el *HTMLElement) GetInnerTextBySelectorAll(_ context.Context, selector val
return arr, nil
}
func (el *HTMLElement) CountBySelector(_ context.Context, selector values.String) values.Int {
func (el *HTMLElement) CountBySelector(_ context.Context, selector values.String) (values.Int, error) {
selection := el.selection.Find(selector.String())
if selection == nil {
return values.ZeroInt
return values.ZeroInt, nil
}
return values.NewInt(selection.Size())
return values.NewInt(selection.Size()), nil
}
func (el *HTMLElement) ExistsBySelector(_ context.Context, selector values.String) (values.Boolean, error) {
@ -560,7 +560,11 @@ func (el *HTMLElement) ensureStyles(ctx context.Context) error {
}
func (el *HTMLElement) parseStyles(ctx context.Context) (*values.Object, error) {
str := el.GetAttribute(ctx, "style")
str, err := el.GetAttribute(ctx, "style")
if err != nil {
return values.NewObject(), err
}
if str == values.None {
return values.NewObject(), nil

View File

@ -322,8 +322,9 @@ func TestElement(t *testing.T) {
So(err, ShouldBeNil)
v := el.GetValue(context.Background())
v, err := el.GetValue(context.Background())
So(err, ShouldBeNil)
So(v, ShouldEqual, "find")
})
@ -393,8 +394,9 @@ func TestElement(t *testing.T) {
So(err, ShouldBeNil)
found := el.QuerySelector(context.Background(), values.NewString("body .card-img-top:nth-child(1)"))
found, err := el.QuerySelector(context.Background(), values.NewString("body .card-img-top:nth-child(1)"))
So(err, ShouldBeNil)
So(found, ShouldNotEqual, values.None)
v := found.(drivers.HTMLNode).GetNodeName()
@ -415,8 +417,9 @@ func TestElement(t *testing.T) {
So(err, ShouldBeNil)
v := el.CountBySelector(context.Background(), values.NewString("head meta"))
v, err := el.CountBySelector(context.Background(), values.NewString("head meta"))
So(err, ShouldBeNil)
So(v, ShouldEqual, 4)
})
}

View File

@ -30,15 +30,15 @@ type (
GetNodeName() values.String
GetChildNodes(ctx context.Context) core.Value
GetChildNodes(ctx context.Context) (*values.Array, error)
GetChildNode(ctx context.Context, idx values.Int) core.Value
GetChildNode(ctx context.Context, idx values.Int) (core.Value, error)
QuerySelector(ctx context.Context, selector values.String) core.Value
QuerySelector(ctx context.Context, selector values.String) (core.Value, error)
QuerySelectorAll(ctx context.Context, selector values.String) core.Value
QuerySelectorAll(ctx context.Context, selector values.String) (*values.Array, error)
CountBySelector(ctx context.Context, selector values.String) values.Int
CountBySelector(ctx context.Context, selector values.String) (values.Int, error)
ExistsBySelector(ctx context.Context, selector values.String) (values.Boolean, error)
@ -61,7 +61,7 @@ type (
SetInnerHTML(ctx context.Context, innerHTML values.String) error
GetValue(ctx context.Context) core.Value
GetValue(ctx context.Context) (core.Value, error)
SetValue(ctx context.Context, value core.Value) error
@ -75,9 +75,9 @@ type (
RemoveStyle(ctx context.Context, name ...values.String) error
GetAttributes(ctx context.Context) *values.Object
GetAttributes(ctx context.Context) (*values.Object, error)
GetAttribute(ctx context.Context, name values.String) core.Value
GetAttribute(ctx context.Context, name values.String) (core.Value, error)
SetAttributes(ctx context.Context, values *values.Object) error

View File

@ -27,7 +27,11 @@ func AttributeGet(ctx context.Context, args ...core.Value) (core.Value, error) {
names := args[1:]
result := values.NewObject()
attrs := el.GetAttributes(ctx)
attrs, err := el.GetAttributes(ctx)
if err != nil {
return values.None, err
}
for _, n := range names {
name := values.NewString(n.String())

View File

@ -21,7 +21,7 @@ func Element(ctx context.Context, args ...core.Value) (core.Value, error) {
return values.None, err
}
return el.QuerySelector(ctx, selector), nil
return el.QuerySelector(ctx, selector)
}
func queryArgs(args []core.Value) (drivers.HTMLElement, values.String, error) {

View File

@ -19,5 +19,5 @@ func Elements(ctx context.Context, args ...core.Value) (core.Value, error) {
return values.None, err
}
return el.QuerySelectorAll(ctx, selector), nil
return el.QuerySelectorAll(ctx, selector)
}

View File

@ -19,5 +19,5 @@ func ElementsCount(ctx context.Context, args ...core.Value) (core.Value, error)
return values.None, err
}
return el.CountBySelector(ctx, selector), nil
return el.CountBySelector(ctx, selector)
}

View File

@ -57,7 +57,11 @@ func Hover(ctx context.Context, args ...core.Value) (core.Value, error) {
return values.None, n.Hover(ctx)
}
found := n.QuerySelector(ctx, selector)
found, err := n.QuerySelector(ctx, selector)
if err != nil {
return values.None, err
}
if found == values.None {
return values.None, core.Errorf(core.ErrNotFound, "element by selector %s", selector)