use a failing matcher if selector fails to compile, adjust tests

This commit is contained in:
Martin Angers
2016-06-15 09:27:17 -04:00
parent 9cc531274b
commit 2ab590df05
10 changed files with 81 additions and 61 deletions

View File

@@ -101,13 +101,13 @@ func TestSlice(t *testing.T) {
}
func TestSliceEmpty(t *testing.T) {
sel := Doc().Find("x").Slice(0, 2)
assertLength(t, sel.Nodes, 0)
defer assertPanic(t)
Doc().Find("x").Slice(0, 2)
}
func TestSliceInvalid(t *testing.T) {
sel := Doc().Find("").Slice(0, 2)
assertLength(t, sel.Nodes, 0)
defer assertPanic(t)
Doc().Find("").Slice(0, 2)
}
func TestSliceOutOfBounds(t *testing.T) {

View File

@@ -1,16 +1,13 @@
package goquery
import (
"github.com/andybalholm/cascadia"
"golang.org/x/net/html"
)
import "golang.org/x/net/html"
// Add adds the selector string's matching nodes to those in the current
// selection and returns a new Selection object.
// The selector string is run in the context of the document of the current
// Selection object.
func (s *Selection) Add(selector string) *Selection {
return s.AddNodes(findWithMatcher([]*html.Node{s.document.rootNode}, cascadia.MustCompile(selector))...)
return s.AddNodes(findWithMatcher([]*html.Node{s.document.rootNode}, compileMatcher(selector))...)
}
// AddMatcher adds the matcher's matching nodes to those in the current

View File

@@ -12,8 +12,8 @@ func TestAdd(t *testing.T) {
func TestAddInvalid(t *testing.T) {
sel1 := Doc().Find("div.row-fluid")
sel2 := sel1.Add("")
assertLength(t, sel1.Nodes, 19)
assertLength(t, sel2.Nodes, 19)
assertLength(t, sel1.Nodes, 9)
assertLength(t, sel2.Nodes, 9)
if sel1 == sel2 {
t.Errorf("selections should not be the same")
}

View File

@@ -1,14 +1,11 @@
package goquery
import (
"github.com/andybalholm/cascadia"
"golang.org/x/net/html"
)
import "golang.org/x/net/html"
// Filter reduces the set of matched elements to those that match the selector string.
// It returns a new Selection object for this subset of matching elements.
func (s *Selection) Filter(selector string) *Selection {
return s.FilterMatcher(cascadia.MustCompile(selector))
return s.FilterMatcher(compileMatcher(selector))
}
// FilterMatcher reduces the set of matched elements to those that match
@@ -21,7 +18,7 @@ func (s *Selection) FilterMatcher(m Matcher) *Selection {
// Not removes elements from the Selection that match the selector string.
// It returns a new Selection object with the matching elements removed.
func (s *Selection) Not(selector string) *Selection {
return s.NotMatcher(cascadia.MustCompile(selector))
return s.NotMatcher(compileMatcher(selector))
}
// NotMatcher removes elements from the Selection that match the given matcher.

View File

@@ -3,7 +3,6 @@ package goquery
import (
"strings"
"github.com/andybalholm/cascadia"
"golang.org/x/net/html"
)
@@ -15,7 +14,7 @@ import (
//
// This follows the same rules as Selection.Append.
func (s *Selection) After(selector string) *Selection {
return s.AfterMatcher(cascadia.MustCompile(selector))
return s.AfterMatcher(compileMatcher(selector))
}
// AfterMatcher applies the matcher from the root document and inserts the matched elements
@@ -66,7 +65,7 @@ func (s *Selection) AfterNodes(ns ...*html.Node) *Selection {
// appended to all target locations except the last one, which will be moved
// as noted in (2).
func (s *Selection) Append(selector string) *Selection {
return s.AppendMatcher(cascadia.MustCompile(selector))
return s.AppendMatcher(compileMatcher(selector))
}
// AppendMatcher appends the elements specified by the matcher to the end of each element
@@ -103,7 +102,7 @@ func (s *Selection) AppendNodes(ns ...*html.Node) *Selection {
//
// This follows the same rules as Selection.Append.
func (s *Selection) Before(selector string) *Selection {
return s.BeforeMatcher(cascadia.MustCompile(selector))
return s.BeforeMatcher(compileMatcher(selector))
}
// BeforeMatcher inserts the matched elements before each element in the set of matched elements.
@@ -165,7 +164,7 @@ func (s *Selection) Empty() *Selection {
// Prepend prepends the elements specified by the selector to each element in
// the set of matched elements, following the same rules as Append.
func (s *Selection) Prepend(selector string) *Selection {
return s.PrependMatcher(cascadia.MustCompile(selector))
return s.PrependMatcher(compileMatcher(selector))
}
// PrependMatcher prepends the elements specified by the matcher to each
@@ -216,7 +215,7 @@ func (s *Selection) Remove() *Selection {
// RemoveFiltered removes the set of matched elements by selector.
// It returns the Selection of removed nodes.
func (s *Selection) RemoveFiltered(selector string) *Selection {
return s.RemoveMatcher(cascadia.MustCompile(selector))
return s.RemoveMatcher(compileMatcher(selector))
}
// RemoveMatcher removes the set of matched elements.
@@ -231,7 +230,7 @@ func (s *Selection) RemoveMatcher(m Matcher) *Selection {
//
// This follows the same rules as Selection.Append.
func (s *Selection) ReplaceWith(selector string) *Selection {
return s.ReplaceWithMatcher(cascadia.MustCompile(selector))
return s.ReplaceWithMatcher(compileMatcher(selector))
}
// ReplaceWithMatcher replaces each element in the set of matched elements with
@@ -293,7 +292,7 @@ func (s *Selection) Unwrap() *Selection {
//
// It returns the original set of elements.
func (s *Selection) Wrap(selector string) *Selection {
return s.WrapMatcher(cascadia.MustCompile(selector))
return s.WrapMatcher(compileMatcher(selector))
}
// WrapMatcher wraps each element in the set of matched elements inside the
@@ -345,7 +344,7 @@ func (s *Selection) wrapNodes(ns ...*html.Node) *Selection {
//
// It returns the original set of elements.
func (s *Selection) WrapAll(selector string) *Selection {
return s.WrapAllMatcher(cascadia.MustCompile(selector))
return s.WrapAllMatcher(compileMatcher(selector))
}
// WrapAllMatcher wraps a single HTML structure, matched by the given Matcher,
@@ -415,7 +414,7 @@ func (s *Selection) WrapAllNode(n *html.Node) *Selection {
//
// It returns the original set of elements.
func (s *Selection) WrapInner(selector string) *Selection {
return s.WrapInnerMatcher(cascadia.MustCompile(selector))
return s.WrapInnerMatcher(compileMatcher(selector))
}
// WrapInnerMatcher wraps an HTML structure, matched by the given selector,

View File

@@ -1,15 +1,12 @@
package goquery
import (
"github.com/andybalholm/cascadia"
"golang.org/x/net/html"
)
import "golang.org/x/net/html"
// Is checks the current matched set of elements against a selector and
// returns true if at least one of these elements matches.
func (s *Selection) Is(selector string) bool {
if len(s.Nodes) > 0 {
return s.IsMatcher(cascadia.MustCompile(selector))
return s.IsMatcher(compileMatcher(selector))
}
return false

View File

@@ -1,9 +1,6 @@
package goquery
import (
"github.com/andybalholm/cascadia"
"golang.org/x/net/html"
)
import "golang.org/x/net/html"
type siblingType int
@@ -24,7 +21,7 @@ const (
// elements, filtered by a selector. It returns a new Selection object
// containing these matched elements.
func (s *Selection) Find(selector string) *Selection {
return pushStack(s, findWithMatcher(s.Nodes, cascadia.MustCompile(selector)))
return pushStack(s, findWithMatcher(s.Nodes, compileMatcher(selector)))
}
// FindMatcher gets the descendants of each element in the current set of matched
@@ -93,7 +90,7 @@ func (s *Selection) Children() *Selection {
// filtered by the specified selector. It returns a new
// Selection object containing these elements.
func (s *Selection) ChildrenFiltered(selector string) *Selection {
return filterAndPush(s, getChildrenNodes(s.Nodes, siblingAll), cascadia.MustCompile(selector))
return filterAndPush(s, getChildrenNodes(s.Nodes, siblingAll), compileMatcher(selector))
}
// ChildrenMatcher gets the child elements of each element in the Selection,
@@ -112,7 +109,7 @@ func (s *Selection) Parent() *Selection {
// ParentFiltered gets the parent of each element in the Selection filtered by a
// selector. It returns a new Selection object containing the matched elements.
func (s *Selection) ParentFiltered(selector string) *Selection {
return filterAndPush(s, getParentNodes(s.Nodes), cascadia.MustCompile(selector))
return filterAndPush(s, getParentNodes(s.Nodes), compileMatcher(selector))
}
// ParentMatcher gets the parent of each element in the Selection filtered by a
@@ -124,7 +121,7 @@ func (s *Selection) ParentMatcher(m Matcher) *Selection {
// Closest gets the first element that matches the selector by testing the
// element itself and traversing up through its ancestors in the DOM tree.
func (s *Selection) Closest(selector string) *Selection {
cs := cascadia.MustCompile(selector)
cs := compileMatcher(selector)
return s.ClosestMatcher(cs)
}
@@ -177,7 +174,7 @@ func (s *Selection) Parents() *Selection {
// ParentsFiltered gets the ancestors of each element in the current
// Selection. It returns a new Selection object with the matched elements.
func (s *Selection) ParentsFiltered(selector string) *Selection {
return filterAndPush(s, getParentsNodes(s.Nodes, nil, nil), cascadia.MustCompile(selector))
return filterAndPush(s, getParentsNodes(s.Nodes, nil, nil), compileMatcher(selector))
}
// ParentsMatcher gets the ancestors of each element in the current
@@ -190,7 +187,7 @@ func (s *Selection) ParentsMatcher(m Matcher) *Selection {
// not including the element matched by the selector. It returns a new Selection
// object containing the matched elements.
func (s *Selection) ParentsUntil(selector string) *Selection {
return pushStack(s, getParentsNodes(s.Nodes, cascadia.MustCompile(selector), nil))
return pushStack(s, getParentsNodes(s.Nodes, compileMatcher(selector), nil))
}
// ParentsUntilMatcher gets the ancestors of each element in the Selection, up to but
@@ -221,7 +218,7 @@ func (s *Selection) ParentsUntilNodes(nodes ...*html.Node) *Selection {
// results based on a selector string. It returns a new Selection
// object containing the matched elements.
func (s *Selection) ParentsFilteredUntil(filterSelector, untilSelector string) *Selection {
return filterAndPush(s, getParentsNodes(s.Nodes, cascadia.MustCompile(untilSelector), nil), cascadia.MustCompile(filterSelector))
return filterAndPush(s, getParentsNodes(s.Nodes, compileMatcher(untilSelector), nil), compileMatcher(filterSelector))
}
// ParentsFilteredUntilMatcher is like ParentsUntilMatcher, with the option to filter the
@@ -234,7 +231,7 @@ func (s *Selection) ParentsFilteredUntilMatcher(filter, until Matcher) *Selectio
// option to filter the results based on a selector string. It returns a new
// Selection object containing the matched elements.
func (s *Selection) ParentsFilteredUntilSelection(filterSelector string, sel *Selection) *Selection {
return s.ParentsMatcherUntilSelection(cascadia.MustCompile(filterSelector), sel)
return s.ParentsMatcherUntilSelection(compileMatcher(filterSelector), sel)
}
// ParentsMatcherUntilSelection is like ParentsUntilSelection, with the
@@ -251,7 +248,7 @@ func (s *Selection) ParentsMatcherUntilSelection(filter Matcher, sel *Selection)
// option to filter the results based on a selector string. It returns a new
// Selection object containing the matched elements.
func (s *Selection) ParentsFilteredUntilNodes(filterSelector string, nodes ...*html.Node) *Selection {
return filterAndPush(s, getParentsNodes(s.Nodes, nil, nodes), cascadia.MustCompile(filterSelector))
return filterAndPush(s, getParentsNodes(s.Nodes, nil, nodes), compileMatcher(filterSelector))
}
// ParentsMatcherUntilNodes is like ParentsUntilNodes, with the
@@ -271,7 +268,7 @@ func (s *Selection) Siblings() *Selection {
// filtered by a selector. It returns a new Selection object containing the
// matched elements.
func (s *Selection) SiblingsFiltered(selector string) *Selection {
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingAll, nil, nil), cascadia.MustCompile(selector))
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingAll, nil, nil), compileMatcher(selector))
}
// SiblingsMatcher gets the siblings of each element in the Selection
@@ -291,7 +288,7 @@ func (s *Selection) Next() *Selection {
// Selection filtered by a selector. It returns a new Selection object
// containing the matched elements.
func (s *Selection) NextFiltered(selector string) *Selection {
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNext, nil, nil), cascadia.MustCompile(selector))
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNext, nil, nil), compileMatcher(selector))
}
// NextMatcher gets the immediately following sibling of each element in the
@@ -311,7 +308,7 @@ func (s *Selection) NextAll() *Selection {
// Selection filtered by a selector. It returns a new Selection object
// containing the matched elements.
func (s *Selection) NextAllFiltered(selector string) *Selection {
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNextAll, nil, nil), cascadia.MustCompile(selector))
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNextAll, nil, nil), compileMatcher(selector))
}
// NextAllMatcher gets all the following siblings of each element in the
@@ -331,7 +328,7 @@ func (s *Selection) Prev() *Selection {
// Selection filtered by a selector. It returns a new Selection object
// containing the matched elements.
func (s *Selection) PrevFiltered(selector string) *Selection {
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrev, nil, nil), cascadia.MustCompile(selector))
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrev, nil, nil), compileMatcher(selector))
}
// PrevMatcher gets the immediately preceding sibling of each element in the
@@ -351,7 +348,7 @@ func (s *Selection) PrevAll() *Selection {
// Selection filtered by a selector. It returns a new Selection object
// containing the matched elements.
func (s *Selection) PrevAllFiltered(selector string) *Selection {
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrevAll, nil, nil), cascadia.MustCompile(selector))
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrevAll, nil, nil), compileMatcher(selector))
}
// PrevAllMatcher gets all the preceding siblings of each element in the
@@ -366,7 +363,7 @@ func (s *Selection) PrevAllMatcher(m Matcher) *Selection {
// object containing the matched elements.
func (s *Selection) NextUntil(selector string) *Selection {
return pushStack(s, getSiblingNodes(s.Nodes, siblingNextUntil,
cascadia.MustCompile(selector), nil))
compileMatcher(selector), nil))
}
// NextUntilMatcher gets all following siblings of each element up to but not
@@ -400,7 +397,7 @@ func (s *Selection) NextUntilNodes(nodes ...*html.Node) *Selection {
// object containing the matched elements.
func (s *Selection) PrevUntil(selector string) *Selection {
return pushStack(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
cascadia.MustCompile(selector), nil))
compileMatcher(selector), nil))
}
// PrevUntilMatcher gets all preceding siblings of each element up to but not
@@ -434,7 +431,7 @@ func (s *Selection) PrevUntilNodes(nodes ...*html.Node) *Selection {
// It returns a new Selection object containing the matched elements.
func (s *Selection) NextFilteredUntil(filterSelector, untilSelector string) *Selection {
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNextUntil,
cascadia.MustCompile(untilSelector), nil), cascadia.MustCompile(filterSelector))
compileMatcher(untilSelector), nil), compileMatcher(filterSelector))
}
// NextFilteredUntilMatcher is like NextUntilMatcher, with the option to filter
@@ -449,7 +446,7 @@ func (s *Selection) NextFilteredUntilMatcher(filter, until Matcher) *Selection {
// option to filter the results based on a selector string. It returns a new
// Selection object containing the matched elements.
func (s *Selection) NextFilteredUntilSelection(filterSelector string, sel *Selection) *Selection {
return s.NextMatcherUntilSelection(cascadia.MustCompile(filterSelector), sel)
return s.NextMatcherUntilSelection(compileMatcher(filterSelector), sel)
}
// NextMatcherUntilSelection is like NextUntilSelection, with the
@@ -467,7 +464,7 @@ func (s *Selection) NextMatcherUntilSelection(filter Matcher, sel *Selection) *S
// Selection object containing the matched elements.
func (s *Selection) NextFilteredUntilNodes(filterSelector string, nodes ...*html.Node) *Selection {
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNextUntil,
nil, nodes), cascadia.MustCompile(filterSelector))
nil, nodes), compileMatcher(filterSelector))
}
// NextMatcherUntilNodes is like NextUntilNodes, with the
@@ -483,7 +480,7 @@ func (s *Selection) NextMatcherUntilNodes(filter Matcher, nodes ...*html.Node) *
// It returns a new Selection object containing the matched elements.
func (s *Selection) PrevFilteredUntil(filterSelector, untilSelector string) *Selection {
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
cascadia.MustCompile(untilSelector), nil), cascadia.MustCompile(filterSelector))
compileMatcher(untilSelector), nil), compileMatcher(filterSelector))
}
// PrevFilteredUntilMatcher is like PrevUntilMatcher, with the option to filter
@@ -498,7 +495,7 @@ func (s *Selection) PrevFilteredUntilMatcher(filter, until Matcher) *Selection {
// option to filter the results based on a selector string. It returns a new
// Selection object containing the matched elements.
func (s *Selection) PrevFilteredUntilSelection(filterSelector string, sel *Selection) *Selection {
return s.PrevMatcherUntilSelection(cascadia.MustCompile(filterSelector), sel)
return s.PrevMatcherUntilSelection(compileMatcher(filterSelector), sel)
}
// PrevMatcherUntilSelection is like PrevUntilSelection, with the
@@ -516,7 +513,7 @@ func (s *Selection) PrevMatcherUntilSelection(filter Matcher, sel *Selection) *S
// Selection object containing the matched elements.
func (s *Selection) PrevFilteredUntilNodes(filterSelector string, nodes ...*html.Node) *Selection {
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
nil, nodes), cascadia.MustCompile(filterSelector))
nil, nodes), compileMatcher(filterSelector))
}
// PrevMatcherUntilNodes is like PrevUntilNodes, with the

View File

@@ -168,7 +168,7 @@ func TestParentsUntil(t *testing.T) {
func TestParentsUntilInvalid(t *testing.T) {
sel := Doc().Find(".container-fluid").ParentsUntil("")
assertLength(t, sel.Nodes, 666) // TODO : ?
assertLength(t, sel.Nodes, 8)
}
func TestParentsUntilRollback(t *testing.T) {
@@ -454,7 +454,7 @@ func TestNextUntil(t *testing.T) {
func TestNextUntilInvalid(t *testing.T) {
sel := Doc().Find(".alert a").NextUntil("")
assertLength(t, sel.Nodes, 100) // TODO : ?
assertLength(t, sel.Nodes, 2)
}
func TestNextUntil2(t *testing.T) {
@@ -513,7 +513,7 @@ func TestPrevUntil(t *testing.T) {
func TestPrevUntilInvalid(t *testing.T) {
sel := Doc().Find(".alert p").PrevUntil("")
assertLength(t, sel.Nodes, 100) // TODO : ?
assertLength(t, sel.Nodes, 2)
}
func TestPrevUntil2(t *testing.T) {

20
type.go
View File

@@ -6,6 +6,8 @@ import (
"net/http"
"net/url"
"github.com/andybalholm/cascadia"
"golang.org/x/net/html"
)
@@ -113,3 +115,21 @@ type Matcher interface {
MatchAll(*html.Node) []*html.Node
Filter([]*html.Node) []*html.Node
}
// compileMatcher compiles the selector string s and returns
// the corresponding Matcher. If s is an invalid selector string,
// it returns a Matcher that fails all matches.
func compileMatcher(s string) Matcher {
cs, err := cascadia.Compile(s)
if err != nil {
return invalidMatcher{}
}
return cs
}
// invalidMatcher is a Matcher that always fails to match.
type invalidMatcher struct{}
func (invalidMatcher) Match(n *html.Node) bool { return false }
func (invalidMatcher) MatchAll(n *html.Node) []*html.Node { return nil }
func (invalidMatcher) Filter(ns []*html.Node) []*html.Node { return nil }

View File

@@ -108,6 +108,19 @@ func printSel(t *testing.T, sel *Selection) {
}
}
func shortPrintSel(t *testing.T, sel *Selection) {
sel.Each(func(i int, s *Selection) {
h, _ := OuterHtml(s)
if ix := strings.Index(h, "\n"); ix >= 0 {
h = h[:ix]
}
if len(h) > 100 {
h = h[:100]
}
fmt.Println(i, ">>> ", h)
})
}
func loadDoc(page string) *Document {
var f *os.File
var e error